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 |