Class: RuboCop::Cop::DevDoc::Style::AvoidSend
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Style::AvoidSend
- Defined in:
- lib/rubocop/cop/dev_doc/style/avoid_send.rb
Overview
Avoid dynamic ‘send` and `public_send` with an explicit receiver.
## Rationale ‘send()` can call any method, including destructive ones like `destroy`. The risk is specifically with dynamic method names —when the argument is a variable or interpolated string, a crafted value could invoke methods the developer never intended to expose.
**Literal symbol arguments are exempt** — the method name is fixed at code-write time and visible to reviewers, equivalent to a direct call.
## 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}")
Constant Summary collapse
- MSG =
"Avoid dynamic `%<method>s` — use bracket notation for model attributes, " \ "or a prefix (`obj.send(\"export_\#{x}\")`) to restrict callable methods.".freeze
- RESTRICT_ON_SEND =
%i[send public_send].freeze
Instance Method Summary collapse
Instance Method Details
#on_send(node) ⇒ Object
56 57 58 59 60 61 |
# File 'lib/rubocop/cop/dev_doc/style/avoid_send.rb', line 56 def on_send(node) return if node.receiver.nil? return if node.first_argument&.sym_type? add_offense(node.loc.selector, message: format(MSG, method: node.method_name)) end |