Skip to content

Restore the Error middleware's two defaults without restating every option - #3030

Merged
ericproulx merged 1 commit into
masterfrom
refactor/error-middleware-options
Oct 11, 2026
Merged

ericproulx merged 1 commit into
masterfrom
refactor/error-middleware-options

Conversation

@ericproulx

Copy link
Copy Markdown
Contributor

Middleware::Error::Options lists its fourteen options as Data members and again as keyword parameters with their defaults. Two of them, rescue_options and default_error_formatter, arrive as an explicit nil from Endpoint#error_middleware_options when the API called no rescue_from and no format. An explicit nil bypasses a keyword default, so initialize restored the two by hand, in a super call that named all fourteen options a third time.

Change

rescue_options ||= Grape::DSL::RescueOptions.new
default_error_formatter ||= Grape::ErrorFormatter::Txt
super

A bare super passes the method's parameters as they stand, reassigned ones included. Checked on Ruby 4.0.7: explicit nils for the other options still go through as nil, an unknown keyword still raises, and positional construction and #with still work. The comment no longer points at the def_delegator :rescue_options, :backtrace that #initialize replaced with an instance variable.

Not changed: the readers and the instance-variable copy

The middleware lists the options twice more, in attr_reader and in the assignments in #initialize. Both could come from Options.members, but a loop costs build time. Copying through instance_variable_set made Error.new 43% slower in the interpreter and 49% with YJIT. With the instance-variable names precomputed and the values read off options, it was still 14% and 23% slower. Compiling a 200-route API was 1.7% and 2.8% slower in every run. Generating the assignments with class_eval would cost nothing, but Grape has no string-eval code generation, and a tidy-up is not a reason to introduce it. The lists stay written out.

Tests

No spec changes; behaviour is unchanged.

  • bundle exec rake passes.
  • Removing either restored default fails the suite: 1584 examples without rescue_options, 34 without default_error_formatter.
  • A script built Error and Formatter bare, with explicit nils and with every option set, on master and on this branch. It dumped instance variables (names and order), reader values and #options; the dumps are identical.
  • Error.new throughput, master vs branch run alternately, two rounds: interpreter 350k → 355k, YJIT 480k → 464k. Master's own two YJIT rounds were 461k and 500k, so this is noise.

🤖 Generated with Claude Code

@ericproulx
ericproulx force-pushed the refactor/error-middleware-options branch from ad3a9d6 to 79141d3 Compare October 10, 2026 23:12
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Danger Report

No issues found.

View run

…ption

Middleware::Error::Options restores the defaults of rescue_options and
default_error_formatter, which arrive as an explicit nil when the API
called no rescue_from and no format. It did so with a super call that
named all fourteen options again, a third list of them after the members
and the keyword parameters.

The two parameters are now reassigned and handed over by a bare super,
which passes parameters as they stand. The comment no longer points at the
def_delegator that #initialize stopped using.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ericproulx
ericproulx force-pushed the refactor/error-middleware-options branch from 79141d3 to 23e5718 Compare October 11, 2026 08:17
@ericproulx
ericproulx merged commit 40b16bb into master Oct 11, 2026
69 checks passed
@ericproulx
ericproulx deleted the refactor/error-middleware-options branch October 11, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant