diff --git a/CHANGELOG.md b/CHANGELOG.md index 13d779fe58..e1b9ff8756 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### Changes + +* [#404](https://github.com/rubocop-hq/rubocop-rails/issues/404): Make `Rails/HelperInstanceVariable` accepts of instance variables when a class which inherits `ActionView::Helpers::FormBuilder`. ([@koic][]) + ## 2.9.0 (2020-12-09) ### New features diff --git a/docs/modules/ROOT/pages/cops_rails.adoc b/docs/modules/ROOT/pages/cops_rails.adoc index ff08803f61..03bd6dcdb5 100644 --- a/docs/modules/ROOT/pages/cops_rails.adoc +++ b/docs/modules/ROOT/pages/cops_rails.adoc @@ -1622,6 +1622,9 @@ If it seems awkward to explicitly pass in each dependent variable, consider moving the behaviour elsewhere, for example to a model, decorator or presenter. +Provided that a class inherits `ActionView::Helpers::FormBuilder`, +an offense will not be registered. + === Examples [source,ruby] @@ -1635,6 +1638,11 @@ end def welcome_message(user) "Hello #{user.name}" end + +# good +class MyFormBuild < ActionView::Helpers::FormBuilder + @template.do_something +end ---- === Configurable attributes diff --git a/lib/rubocop/cop/rails/helper_instance_variable.rb b/lib/rubocop/cop/rails/helper_instance_variable.rb index aab061aeaf..69d9985700 100644 --- a/lib/rubocop/cop/rails/helper_instance_variable.rb +++ b/lib/rubocop/cop/rails/helper_instance_variable.rb @@ -13,6 +13,9 @@ module Rails # variable, consider moving the behaviour elsewhere, for # example to a model, decorator or presenter. # + # Provided that a class inherits `ActionView::Helpers::FormBuilder`, + # an offense will not be registered. + # # @example # # bad # def welcome_message @@ -23,18 +26,35 @@ module Rails # def welcome_message(user) # "Hello #{user.name}" # end + # + # # good + # class MyFormBuilder < ActionView::Helpers::FormBuilder + # @template.do_something + # end class HelperInstanceVariable < Base MSG = 'Do not use instance variables in helpers.' def on_ivar(node) + return if form_builder?(node) + add_offense(node) end def on_ivasgn(node) - return if node.parent.or_asgn_type? + return if node.parent.or_asgn_type? || form_builder?(node) add_offense(node.loc.name) end + + private + + def form_builder?(node) + node.each_ancestor(:class) do |class_node| + return true if class_node.parent_class&.source == 'ActionView::Helpers::FormBuilder' + end + + false + end end end end diff --git a/spec/rubocop/cop/rails/helper_instance_variable_spec.rb b/spec/rubocop/cop/rails/helper_instance_variable_spec.rb index f8fe47a406..8a407a024e 100644 --- a/spec/rubocop/cop/rails/helper_instance_variable_spec.rb +++ b/spec/rubocop/cop/rails/helper_instance_variable_spec.rb @@ -36,4 +36,28 @@ def foo end RUBY end + + it 'does not register an offense when a class which inherits `ActionView::Helpers::FormBuilder`' do + expect_no_offenses(<<~'RUBY') + class MyFormBuilder < ActionView::Helpers::FormBuilder + def do_something + @template + @template = do_something + end + end + RUBY + end + + it 'registers an offense when using a class which does not inherit `ActionView::Helpers::FormBuilder`' do + expect_offense(<<~'RUBY') + class Foo + def do_something + @template + ^^^^^^^^^ Do not use instance variables in helpers. + @template = do_something + ^^^^^^^^^ Do not use instance variables in helpers. + end + end + RUBY + end end