Add Grape.config.warn_on_helper_overrides (opt-in dev-time signal)#2705
Conversation
fd4173b to
1a1e00b
Compare
Danger ReportNo issues found. |
1a1e00b to
ddf8bc0
Compare
|
Thanks for this — @dblock prompted me (Copilot) to suggest an alternative worth considering. Rather than a global flag, what if the warning were always on but silenced at the point of definition using the familiar Ruby method-modifier pattern? helpers do
override def params # explicit intent — no warning
"overridden"
end
def logger # warns: shadows Grape::Endpoint#logger
MyApp.logger
end
end
module BaseHelper
def override(method_name)
@intentional_overrides ||= Set.new
@intentional_overrides << method_name
method_name
end
endThe check skips anything in |
ddf8bc0 to
ec0bce4
Compare
|
@dblock thanks (and tell Copilot thanks too) — the 1. Backwards compatibility for the documented patternThe pattern this PR's UPGRADING note was originally responding to — class MyAPI < Grape::API
logger Logger.new($stdout)
helpers do
def logger
MyAPI.logger
end
end
end— is documented and was used in The flag inverts this: zero noise for the existing world, the audit is opt-in. 2.
|
A helper method defined via `helpers do; def foo; end; end` is mixed
into the endpoint's singleton class and therefore takes precedence
over `Grape::Endpoint#foo` if one exists. That's the documented and
correct behaviour, but it's silent — when the framework gains a new
method (e.g. `Grape::Endpoint#logger`) and a user already defined a
helper of the same name, nothing tells them their helper now masks
the framework implementation.
Adds an opt-in dev-time signal:
# config/environments/development.rb (or equivalent)
Grape.config.warn_on_helper_overrides = true
When enabled, defining a `helpers` module — either via a block or by
passing an external module to `helpers SomeModule` — emits one
warning to `$stderr` per helper method that masks a `Grape::Endpoint`
instance method. Off by default; zero cost in production.
Enabled in `spec_helper.rb` so future test additions that
accidentally mask `Endpoint` methods via helpers surface as warnings
during CI.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ec0bce4 to
9f28c1a
Compare
|
Your plan is good. |
Adds an opt-in
Grape.config.warn_on_helper_overridesflag. When enabled, defining a helper that masks aGrape::Endpointinstance method emits a warning to$stderr.Follow-up to #2704 — that PR introduced
Grape::Endpoint#logger, which is silently shadowed by any pre-existinghelpers do; def logger; …; end. The helper-wins behaviour is correct (singleton_class.include(@helpers)makes it so), but it's invisible. This PR gives users a way to find out.Usage
Behaviour
def logger; MyAPI.logger; endpattern) won't suddenly start warning when they upgrade.helpersdefinition. Boot-time only —helpersruns at class definition, not per request.helpers do; def foo; end; endandhelpers SomeModulewhereSomeModuledefines an instance method colliding withEndpoint.Files
lib/grape.rbsetting :warn_on_helper_overrides, default: false.lib/grape/dsl/helpers.rbinject_api_helpers_to_modnow calls a new privatewarn_on_endpoint_overrides(mod)when the flag is on.spec/grape/dsl/helpers_spec.rbCHANGELOG.mdTest plan
bundle exec rspec spec/grape/dsl/helpers_spec.rb— 11 examples, 0 failures (5 new + 6 existing)bundle exec rspec— full suite green (2,259 examples, up from 2,254)bundle exec rubocop lib/ spec/— cleanWhy opt-in
Plenty of existing apps deliberately override Endpoint methods via helpers. An always-on warning would force-rename every one of them on upgrade. Off-by-default keeps the framework friendly, while the flag gives anyone who wants the signal a one-line opt-in. Suggested home is
config/environments/development.rbso prod stays quiet.🤖 Generated with Claude Code