Skip to content

Commit

Permalink
Add Rails/TopLevelHashWithIndifferentAccess cop
Browse files Browse the repository at this point in the history
  • Loading branch information
r7kamura committed Jul 29, 2022
1 parent 8d3de8e commit 2baf744
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 0 deletions.
@@ -0,0 +1 @@
* [#752](https://github.com/rubocop/rubocop-rails/pull/752): Add `Rails/TopLevelHashWithIndifferentAccess` cop. ([@r7kamura][])
6 changes: 6 additions & 0 deletions config/default.yml
Expand Up @@ -958,6 +958,12 @@ Rails/ToSWithArgument:
Safe: false
VersionAdded: '<<next>>'

Rails/TopLevelHashWithIndifferentAccess:
Description: 'Identifies top-level `HashWithIndifferentAccess`.'
Reference: 'https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#top-level-hashwithindifferentaccess-is-soft-deprecated'
Enabled: pending
VersionAdded: '<<next>>'

Rails/TransactionExitStatement:
Description: 'Avoid the usage of `return`, `break` and `throw` in transaction blocks.'
Enabled: pending
Expand Down
48 changes: 48 additions & 0 deletions lib/rubocop/cop/rails/top_level_hash_with_indifferent_access.rb
@@ -0,0 +1,48 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Rails
# Identifies top-level `HashWithIndifferentAccess`.
# This has been soft-deprecated since Rails 5.1.
#
# @example
# # bad
# HashWithIndifferentAccess.new(foo: 'bar')
#
# # good
# ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
#
class TopLevelHashWithIndifferentAccess < Base
extend AutoCorrector
extend TargetRailsVersion

minimum_target_rails_version 5.1

MSG = 'Avoid top-level `HashWithIndifferentAccess`.'

# @!method top_level_hash_with_indifferent_access?(node)
# @param [RuboCop::AST::ConstNode] node
# @return [Boolean]
def_node_matcher :top_level_hash_with_indifferent_access?, <<~PATTERN
(const {nil? cbase} :HashWithIndifferentAccess)
PATTERN

# @param [RuboCop::AST::ConstNode] node
def on_const(node)
return unless top_level_hash_with_indifferent_access?(node)

add_offense(node) do |corrector|
autocorrect(corrector, node)
end
end

private

def autocorrect(corrector, node)
corrector.insert_before(node.location.name, 'ActiveSupport::')
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/rails_cops.rb
Expand Up @@ -114,6 +114,7 @@
require_relative 'rails/time_zone_assignment'
require_relative 'rails/to_formatted_s'
require_relative 'rails/to_s_with_argument'
require_relative 'rails/top_level_hash_with_indifferent_access'
require_relative 'rails/transaction_exit_statement'
require_relative 'rails/uniq_before_pluck'
require_relative 'rails/unique_validation_without_index'
Expand Down
@@ -0,0 +1,45 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Rails::TopLevelHashWithIndifferentAccess, :config, :rails51 do
context 'with top-level HashWithIndifferentAccess' do
it 'registers and corrects an offense' do
expect_offense(<<~RUBY)
HashWithIndifferentAccess.new(foo: 'bar')
^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid top-level `HashWithIndifferentAccess`.
RUBY

expect_correction(<<~RUBY)
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
RUBY
end
end

context 'with top-level ::HashWithIndifferentAccess' do
it 'registers and corrects an offense' do
expect_offense(<<~RUBY)
::HashWithIndifferentAccess.new(foo: 'bar')
^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid top-level `HashWithIndifferentAccess`.
RUBY

expect_correction(<<~RUBY)
::ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
RUBY
end
end

context 'with ActiveSupport::HashWithIndifferentAccess' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY)
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
RUBY
end
end

context 'with ActiveSupport::HashWithIndifferentAccess on Rails 5.0', :rails50 do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY)
HashWithIndifferentAccess.new(foo: 'bar')
RUBY
end
end
end

0 comments on commit 2baf744

Please sign in to comment.