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

# EnforceForPrefixed: true
# bad
def foo_bar
  foo.bar
end

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

# 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 58
def on_def(node)
  method_name, args, body = *node
  return unless trivial_delegate?(method_name, args, body)
  return if private_or_protected_delegation(node)
  add_offense(node, location: :keyword)
end

Private Instance Methods

arguments_match?(args, body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 92
def arguments_match?(args, body)
  _receiver, _method_name, *arguments = *body
  arg_array = Array(args)
  argument_array = Array(arguments)
  arg_array.size == argument_array.size && (
    arg_array == argument_array ||
    arg_array.map(&:children) == argument_array.map(&:children)
  )
end
autocorrect(node) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 67
def autocorrect(node)
  method_name, _args, body = *node
  delegation = ["delegate :#{body.children[1]}",
                "to: :#{body.children[0].children[1]}"]
  if method_name == prefixed_method_name(body)
    delegation << ['prefix: true']
  end

  lambda do |corrector|
    corrector.replace(node.source_range, delegation.join(', '))
  end
end
delegate?(body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 86
def delegate?(body)
  receiver, = *body
  receiver.respond_to?(:type) && receiver.send_type? &&
    receiver.child_nodes.empty?
end
include_prefix_case?() click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 109
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 102
def method_name_matches?(method_name, body)
  _receiver, property_name, *_args = *body
  method_name == property_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 113
def prefixed_method_name(body)
  receiver, property_name, *_args = *body
  _receiver, target, *_args = *receiver
  [target, property_name].join('_').to_sym
end
private_or_protected_before(line) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 125
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 119
def private_or_protected_delegation(node)
  line = node.loc.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 129
def private_or_protected_inline(line)
  processed_source[line - 1].strip =~ /\A(private )|(protected )/
end
trivial_delegate?(method_name, args, body) click to toggle source
# File lib/rubocop/cop/rails/delegate.rb, line 80
def trivial_delegate?(method_name, args, body)
  body && delegate?(body) && !body.csend_type? &&
    method_name_matches?(method_name, body) &&
    arguments_match?(args, body)
end