Class: RuboCop::Cop::DevDoc::Style::NoUnscopedMethodDefinitions
- Inherits:
-
Base
- Object
- Base
- RuboCop::Cop::DevDoc::Style::NoUnscopedMethodDefinitions
- Defined in:
- lib/rubocop/cop/dev_doc/style/no_unscoped_method_definitions.rb
Overview
Flag ‘def` / `define_method` whose enclosing scope chain does not include a `class` or `module` body — the method lands on `Object`.
## Rationale A ‘def` not inside an explicit `class` or `module` body defines a method on `Object`, even when it visually looks scoped. The most common failure mode is inside Rake’s ‘namespace` block:
❌ Two rake files both define `build_load_plan` — whichever file
loads second silently wins. Tests for one task call the other
task's helper logic without warning.
namespace :faqs do
def build_load_plan(fixtures, by_slug)
...
end
end
✔️ Wrapped in a real Ruby scope — no collision risk.
module FaqsLoader
extend self
def build_load_plan(fixtures, by_slug)
...
end
end
Core’s ‘Style/TopLevelMethodDefinition` catches literal top-level `def` (not inside any block) but misses the rake `namespace` pattern because the `def` is technically inside a `block` node. This cop subsumes that case — disable `Style/TopLevelMethodDefinition` when this cop is enabled to avoid double-flagging.
## Allowlist Some DSLs legitimately define methods inside blocks where the block’s receiver is not ‘Object` (`Struct.new`, `Class.new`, `Module.new`). Configure `SafeDSLReceivers` to extend the allowlist.
Constant Summary collapse
- MSG =
'Define methods inside an explicit `module` or `class`, not at the top level ' \ 'or inside a DSL block (e.g. Rake `namespace`). ' \ 'Methods defined here land on `Object` and can silently collide across files.'.freeze
- DEFAULT_SAFE_DSL_RECEIVERS =
%w[Struct Class Module].freeze
Instance Method Summary collapse
- #on_def(node) ⇒ Object (also: #on_defs)
- #on_send(node) ⇒ Object
Instance Method Details
#on_def(node) ⇒ Object Also known as: on_defs
79 80 81 |
# File 'lib/rubocop/cop/dev_doc/style/no_unscoped_method_definitions.rb', line 79 def on_def(node) add_offense(node.loc.keyword) unless enclosed_in_class_or_module?(node) end |
#on_send(node) ⇒ Object
84 85 86 87 88 89 |
# File 'lib/rubocop/cop/dev_doc/style/no_unscoped_method_definitions.rb', line 84 def on_send(node) return unless node.method_name == :define_method return if enclosed_in_class_or_module?(node) add_offense(node.loc.selector) end |