class RuboCop::Cop::Rails::LexicallyScopedActionFilter
end
end
@content = Article.find(params)
def load_article
private
end
super
def update
# in the superclass, so needs to invoke ‘super`
# the cop requires this method, but it relies on behavior defined
before_action :load_article, only: [:update]
class ArticlesController < ContentController
end
end
@content.update(content_attributes)
def update
class ContentController < ApplicationController
@example
end
end
# something
def foo
end
before_action proc { authenticate }, only: :foo
included do
extend ActiveSupport::Concern
module FooMixin
# good
end
end
before_action proc { authenticate }, only: :foo
included do
extend ActiveSupport::Concern
module FooMixin
# bad
@example
end
end
def logout
end
def settings
end
def index
before_action :require_login, only: %i[index settings logout]
class LoginController < ApplicationController
# good
end
end
def index
before_action :require_login, only: %i[index settings logout]
class LoginController < ApplicationController
# bad
@example
remember to invoke `super` in the subclass actions.
If you rely on behavior defined in the superclass actions, you must
define the filter in that class or module.
methods that are defined in other classes or modules, you should
mixins on the filter, but these can confuse developers. If you specify
You can technically specify methods of superclass or methods added by
@safety
`except` options are defined within the same class or module.
Checks that methods specified in the filter’s ‘only` or
def alias_methods(node)
def alias_methods(node) result = {} node.each_child_node(:send, :alias) do |child_node| case child_node.type when :send if child_node.method?(:alias_method) result[child_node.last_argument.value] = child_node.first_argument.value end when :alias result[child_node.old_identifier.value] = child_node.new_identifier.value end end result end
def aliased_action_methods(node, defined_methods)
def aliased_action_methods(node, defined_methods) alias_methods = alias_methods(node) defined_methods.each_with_object([]) do |defined_method, aliased_method| if (new_method_name = alias_methods[defined_method]) aliased_method << new_method_name end end end
def array_values(node) # rubocop:disable Metrics/MethodLength
-
(Array
-)
Parameters:
-
node
(RuboCop::AST::Node
) --
def array_values(node) # rubocop:disable Metrics/MethodLength case node.type when :str [node.str_content.to_sym] when :sym [node.value] when :array node.values.filter_map do |v| case v.type when :str v.str_content.to_sym when :sym v.value end end else [] end end
def defined_action_methods(block)
def defined_action_methods(block) return [] unless block defined_methods = block.each_child_node(:def).map(&:method_name) defined_methods + delegated_action_methods(block) + aliased_action_methods(block, defined_methods) end
def delegated_action_methods(node)
def delegated_action_methods(node) node.each_child_node(:send).flat_map do |child_node| delegated_methods(child_node) || [] end end
def message(methods, parent)
-
(String)
-
Parameters:
-
parent
(RuboCop::AST::Node
) -- -
methods
(Array
) --
def message(methods, parent) if methods.size == 1 format(MSG, action: "`#{methods[0]}` is", type: parent.type) else format(MSG, action: "`#{methods.join('`, `')}` are", type: parent.type) end end
def on_send(node)
def on_send(node) methods_node = only_or_except_filter_methods(node) return unless methods_node parent = node.each_ancestor(:class, :module).first return unless parent # NOTE: a `:begin` node may not exist if the class/module consists of a single statement block = parent.each_child_node(:begin).first defined_action_methods = defined_action_methods(block) unmatched_methods = array_values(methods_node) - defined_action_methods return if unmatched_methods.empty? message = message(unmatched_methods, parent) add_offense(node, message: message) end