Class: RuboCop::Cop::DevDoc::Style::AvoidSend

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/dev_doc/style/avoid_send.rb

Overview

Avoid ‘send` and `public_send` with an explicit receiver.

## Rationale ‘send()` can call any method, including destructive ones like `destroy`. When the method name is dynamic, this is a real risk — a crafted parameter can invoke methods the developer never intended to expose. If `send()` is unavoidable, add safeguards to restrict which methods can be called.

## Safer alternatives

**a) For model attributes — use bracket notation instead.** ‘@model` only accesses database columns, so it cannot accidentally invoke methods like `destroy`.

 Dangerous  method_name could be :destroy or any other method
@user.send(method_name)

✔️ Safe  only accesses database columns
@user[method_name]

**b) For non-model objects — use a prefix to restrict callable methods.** By interpolating the dynamic part into a fixed prefix, only methods with that prefix (e.g. ‘export_csv`, `export_pdf`) can be invoked, preventing accidental calls to unintended methods.

 Unrestricted  any method can be called
obj.send(method_name)

✔️ Restricted  only methods with the prefix can be called
obj.send("export_#{method_name}")

**c) For known methods — call directly instead of via ‘send`.**

Examples:

# bad
@user.send(method_name)
obj.public_send(action)

# good
@user[attribute_name]
obj.send("export_#{method_name}")

Constant Summary collapse

MSG =
'Avoid `%<method>s` with an explicit receiver. ' \
'Use bracket notation for model attributes, or restrict callable methods with a prefix.'.freeze
RESTRICT_ON_SEND =
%i[send public_send].freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ Object



52
53
54
55
56
# File 'lib/rubocop/cop/dev_doc/style/avoid_send.rb', line 52

def on_send(node)
  return if node.receiver.nil?

  add_offense(node.loc.selector, message: format(MSG, method: node.method_name))
end