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

Inherits:
RuboCop::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

Instance Method Summary collapse

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