Skip to content

Commit e007571

Browse files
authored
Merge pull request #752 from r7kamura/feature/top-lavel-hash
Add `Rails/TopLevelHashWithIndifferentAccess` cop
2 parents 8c40def + 2baf744 commit e007571

File tree

5 files changed

+101
-0
lines changed

5 files changed

+101
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* [#752](https://github.com/rubocop/rubocop-rails/pull/752): Add `Rails/TopLevelHashWithIndifferentAccess` cop. ([@r7kamura][])

config/default.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,12 @@ Rails/ToSWithArgument:
958958
Safe: false
959959
VersionAdded: '<<next>>'
960960

961+
Rails/TopLevelHashWithIndifferentAccess:
962+
Description: 'Identifies top-level `HashWithIndifferentAccess`.'
963+
Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
964+
Enabled: pending
965+
VersionAdded: '<<next>>'
966+
961967
Rails/TransactionExitStatement:
962968
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
963969
Enabled: pending
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# frozen_string_literal: true
2+
3+
module RuboCop
4+
module Cop
5+
module Rails
6+
# Identifies top-level `HashWithIndifferentAccess`.
7+
# This has been soft-deprecated since Rails 5.1.
8+
#
9+
# @example
10+
# # bad
11+
# HashWithIndifferentAccess.new(foo: 'bar')
12+
#
13+
# # good
14+
# ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
15+
#
16+
class TopLevelHashWithIndifferentAccess < Base
17+
extend AutoCorrector
18+
extend TargetRailsVersion
19+
20+
minimum_target_rails_version 5.1
21+
22+
MSG = 'Avoid top-level `HashWithIndifferentAccess`.'
23+
24+
# @!method top_level_hash_with_indifferent_access?(node)
25+
# @param [RuboCop::AST::ConstNode] node
26+
# @return [Boolean]
27+
def_node_matcher :top_level_hash_with_indifferent_access?, <<~PATTERN
28+
(const {nil? cbase} :HashWithIndifferentAccess)
29+
PATTERN
30+
31+
# @param [RuboCop::AST::ConstNode] node
32+
def on_const(node)
33+
return unless top_level_hash_with_indifferent_access?(node)
34+
35+
add_offense(node) do |corrector|
36+
autocorrect(corrector, node)
37+
end
38+
end
39+
40+
private
41+
42+
def autocorrect(corrector, node)
43+
corrector.insert_before(node.location.name, 'ActiveSupport::')
44+
end
45+
end
46+
end
47+
end
48+
end

lib/rubocop/cop/rails_cops.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
require_relative 'rails/time_zone_assignment'
115115
require_relative 'rails/to_formatted_s'
116116
require_relative 'rails/to_s_with_argument'
117+
require_relative 'rails/top_level_hash_with_indifferent_access'
117118
require_relative 'rails/transaction_exit_statement'
118119
require_relative 'rails/uniq_before_pluck'
119120
require_relative 'rails/unique_validation_without_index'
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe RuboCop::Cop::Rails::TopLevelHashWithIndifferentAccess, :config, :rails51 do
4+
context 'with top-level HashWithIndifferentAccess' do
5+
it 'registers and corrects an offense' do
6+
expect_offense(<<~RUBY)
7+
HashWithIndifferentAccess.new(foo: 'bar')
8+
^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid top-level `HashWithIndifferentAccess`.
9+
RUBY
10+
11+
expect_correction(<<~RUBY)
12+
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
13+
RUBY
14+
end
15+
end
16+
17+
context 'with top-level ::HashWithIndifferentAccess' do
18+
it 'registers and corrects an offense' do
19+
expect_offense(<<~RUBY)
20+
::HashWithIndifferentAccess.new(foo: 'bar')
21+
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid top-level `HashWithIndifferentAccess`.
22+
RUBY
23+
24+
expect_correction(<<~RUBY)
25+
::ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
26+
RUBY
27+
end
28+
end
29+
30+
context 'with ActiveSupport::HashWithIndifferentAccess' do
31+
it 'does not register an offense' do
32+
expect_no_offenses(<<~RUBY)
33+
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
34+
RUBY
35+
end
36+
end
37+
38+
context 'with ActiveSupport::HashWithIndifferentAccess on Rails 5.0', :rails50 do
39+
it 'does not register an offense' do
40+
expect_no_offenses(<<~RUBY)
41+
HashWithIndifferentAccess.new(foo: 'bar')
42+
RUBY
43+
end
44+
end
45+
end

0 commit comments

Comments
 (0)