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

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

Overview

Checks that methods specified in the filter’s ‘only` or `except` options are defined within the same class or module.

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 behavior 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.'
RESTRICT_ON_SEND =
%i[
  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
FILTERS =
RESTRICT_ON_SEND.map { |method_name| ":#{method_name}" }

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



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

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