Class: RuboCop::Cop::Rails::LexicallyScopedActionFilter

Inherits:
Cop
  • Object
show all
Defined in:
lib/rubocop/cop/rails/lexically_scoped_action_filter.rb

Overview

This cop checks that methods specified in the filter's `only` or `except` options are defined within the same class or module.

You can technically specify methods of superclass or methods added by mixins on the filter, but these can confuse developers. If you specify methods that are defined in other classes or modules, you should define the filter in that class or module.

If you rely on behaviour defined in the superclass actions, you must remember to invoke `super` in the subclass actions.

Examples:

# bad
class LoginController < ApplicationController
  before_action :require_login, only: %i[index settings logout]

  def index
  end
end

# good
class LoginController < ApplicationController
  before_action :require_login, only: %i[index settings logout]

  def index
  end

  def settings
  end

  def logout
  end
end
# bad
module FooMixin
  extend ActiveSupport::Concern

  included do
    before_action proc { authenticate }, only: :foo
  end
end

# good
module FooMixin
  extend ActiveSupport::Concern

  included do
    before_action proc { authenticate }, only: :foo
  end

  def foo
    # something
  end
end
class ContentController < ApplicationController
  def update
    @content.update(content_attributes)
  end
end

class ArticlesController < ContentController
  before_action :load_article, only: [:update]

  # the cop requires this method, but it relies on behaviour defined
  # in the superclass, so needs to invoke `super`
  def update
    super
  end

  private

  def load_article
    @content = Article.find(params[:article_id])
  end
end

Constant Summary collapse

MSG =
'%<action>s not explicitly defined on the %<type>s.'
FILTERS =
%w[
  :after_action
  :append_after_action
  :append_around_action
  :append_before_action
  :around_action
  :before_action
  :prepend_after_action
  :prepend_around_action
  :prepend_before_action
  :skip_after_action
  :skip_around_action
  :skip_before_action
  :skip_action_callback
].freeze

Constants included from Util

Util::LITERAL_REGEX

Instance Attribute Summary

Attributes inherited from Cop

#config, #corrections, #offenses, #processed_source

Instance Method Summary collapse

Methods inherited from Cop

#add_offense, all, autocorrect_incompatible_with, badge, #config_to_allow_offenses, #config_to_allow_offenses=, #cop_config, cop_name, #cop_name, #correct, department, #duplicate_location?, #excluded_file?, #find_location, #highlights, inherited, #initialize, #join_force?, lint?, match?, #messages, non_rails, #parse, qualified_cop_name, #relevant_file?, #target_rails_version, #target_ruby_version

Methods included from NodePattern::Macros

#def_node_matcher, #def_node_search, #node_search, #node_search_all, #node_search_body, #node_search_first

Methods included from AST::Sexp

#s

Methods included from AutocorrectLogic

#autocorrect?, #autocorrect_enabled?, #autocorrect_requested?, #support_autocorrect?

Methods included from IgnoredNode

#ignore_node, #ignored_node?, #part_of_ignored_node?

Methods included from Util

begins_its_line?, comment_line?, double_quotes_required?, escape_string, first_part_of_call_chain, interpret_string_escapes, line_range, needs_escaping?, on_node, parentheses?, same_line?, to_string_literal, to_supported_styles, tokens, trim_string_interporation_escape_character

Methods included from PathUtil

absolute?, chdir, hidden_dir?, hidden_file_in_not_hidden_dir?, match_path?, pwd, relative_path, reset_pwd, smart_path

Constructor Details

This class inherits a constructor from RuboCop::Cop::Cop

Instance Method Details

#on_send(node) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/rubocop/cop/rails/lexically_scoped_action_filter.rb', line 115

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

  block = parent.each_child_node(:begin).first
  return unless block

  defined_methods = block.each_child_node(:def).map(&:method_name)
  methods = array_values(methods_node).reject do |method|
    defined_methods.include?(method)
  end

  message = message(methods, parent)
  add_offense(node, message: message) unless methods.empty?
end