class RuboCop::Cop::Rails::Delegate

This cop looks for delegations that could have been created automatically with the `delegate` method.

Safe navigation `&.` is ignored because Rails' `allow_nil` option checks not just for nil but also delegates if nil responds to the delegated method.

The `EnforceForPrefixed` option (defaulted to `true`) means that using the target object as a prefix of the method name without using the `delegate` method will be a violation. When set to `false`, this case is legal.

@example

# bad
def bar
  foo.bar
end

# good
delegate :bar, to: :foo

# good
def bar
  foo&.bar
end

# good
private
def bar
  foo.bar
end

@example EnforceForPrefixed: true (default)

# bad
def foo_bar
  foo.bar
end

# good
delegate :bar, to: :foo, prefix: true

@example EnforceForPrefixed: false

# good
def foo_bar
  foo.bar
end

# good
delegate :bar, to: :foo, prefix: true

Constants

MSG

Public Instance Methods

on_def(node) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 65
def on_def(node)
  return unless trivial_delegate?(node)
  return if private_or_protected_delegation(node)

  register_offense(node)
end

Private Instance Methods

arguments_match?(arg_array, body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 89
def arguments_match?(arg_array, body)
  argument_array = body.arguments

  return false if arg_array.size != argument_array.size

  arg_array.zip(argument_array).all? do |arg, argument|
    arg.arg_type? &&
      argument.lvar_type? &&
      arg.children == argument.children
  end
end
include_prefix_case?() click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 106
def include_prefix_case?
  cop_config['EnforceForPrefixed']
end
method_name_matches?(method_name, body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 101
def method_name_matches?(method_name, body)
  method_name == body.method_name ||
    (include_prefix_case? && method_name == prefixed_method_name(body))
end
prefixed_method_name(body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 110
def prefixed_method_name(body)
  [body.receiver.method_name, body.method_name].join('_').to_sym
end
private_or_protected_before(line) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 120
def private_or_protected_before(line)
  (processed_source[0..line].map(&:strip) & %w[private protected]).any?
end
private_or_protected_delegation(node) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 114
def private_or_protected_delegation(node)
  line = node.first_line
  private_or_protected_before(line) ||
    private_or_protected_inline(line)
end
private_or_protected_inline(line) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 124
def private_or_protected_inline(line)
  processed_source[line - 1].strip.match?(/\A(private )|(protected )/)
end
register_offense(node) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 74
def register_offense(node)
  add_offense(node.loc.keyword) do |corrector|
    delegation = ["delegate :#{node.body.method_name}", "to: :#{node.body.receiver.method_name}"]
    delegation << ['prefix: true'] if node.method?(prefixed_method_name(node.body))

    corrector.replace(node.source_range, delegation.join(', '))
  end
end
trivial_delegate?(def_node) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 83
def trivial_delegate?(def_node)
  delegate?(def_node) &&
    method_name_matches?(def_node.method_name, def_node.body) &&
    arguments_match?(def_node.arguments, def_node.body)
end