diff --git a/lib/rubocop/cop/rails/read_write_attribute.rb b/lib/rubocop/cop/rails/read_write_attribute.rb index 7bc262fd6c..97634d232e 100644 --- a/lib/rubocop/cop/rails/read_write_attribute.rb +++ b/lib/rubocop/cop/rails/read_write_attribute.rb @@ -59,12 +59,15 @@ def on_send(node) private def within_shadowing_method?(node) - node.each_ancestor(:def).any? do |enclosing_method| - shadowing_method_name = node.first_argument.value.to_s - shadowing_method_name << '=' if node.method?(:write_attribute) + first_arg = node.first_argument + return false unless first_arg.respond_to?(:value) - enclosing_method.method_name.to_s == shadowing_method_name - end + enclosing_method = node.each_ancestor(:def).first + return false unless enclosing_method + + shadowing_method_name = first_arg.value.to_s + shadowing_method_name << '=' if node.method?(:write_attribute) + enclosing_method.method_name.to_s == shadowing_method_name end def build_message(node) diff --git a/spec/rubocop/cop/rails/read_write_attribute_spec.rb b/spec/rubocop/cop/rails/read_write_attribute_spec.rb index de0c5ecd7c..48bcb30aef 100644 --- a/spec/rubocop/cop/rails/read_write_attribute_spec.rb +++ b/spec/rubocop/cop/rails/read_write_attribute_spec.rb @@ -89,6 +89,42 @@ def foo it 'registers no offense with explicit receiver' do expect_no_offenses('res = object.read_attribute(:test)') end + + context 'when used within a method' do + context 'when using variable for the attribute name' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + def do_the_read_from(column) + read_attribute(column) + ^^^^^^^^^^^^^^^^^^^^^^ Prefer `self[column]`. + end + RUBY + + expect_correction(<<~RUBY) + def do_the_read_from(column) + self[column] + end + RUBY + end + end + + context 'when using constant for the attribute name' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + def do_the_read + read_attribute(ATTR_NAME) + ^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `self[ATTR_NAME]`. + end + RUBY + + expect_correction(<<~RUBY) + def do_the_read + self[ATTR_NAME] + end + RUBY + end + end + end end context 'write_attribute' do @@ -105,6 +141,42 @@ def foo end end + context 'when used within a method' do + context 'when using variable for the attribute name' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + def do_the_write_to(column) + write_attribute(column, 'value') + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `self[column] = 'value'`. + end + RUBY + + expect_correction(<<~RUBY) + def do_the_write_to(column) + self[column] = 'value' + end + RUBY + end + end + + context 'when using constant for the attribute name' do + it 'registers an offense and corrects' do + expect_offense(<<~RUBY) + def do_the_write(value) + write_attribute(ATTR_NAME, value) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `self[ATTR_NAME] = value`. + end + RUBY + + expect_correction(<<~RUBY) + def do_the_write(value) + self[ATTR_NAME] = value + end + RUBY + end + end + end + context 'when using a string for the attribute' do it 'registers an offense and corrects' do expect_offense(<<~RUBY)