Skip to content

Include the parent controller's helper module instead of re-listing its helpers - #2760

Open
ndbroadbent wants to merge 1 commit into
Shopify:mainfrom
DocSpring:nathan/helpers-by-parent
Open

ndbroadbent wants to merge 1 commit into
Shopify:mainfrom
DocSpring:nathan/helpers-by-parent

Conversation

@ndbroadbent

Copy link
Copy Markdown

Motivation

Each controller's generated HelperMethods lists every module in its ancestor chain, including all of its parent controller's. Rails calls helper :all on each direct subclass of ActionController::Base (when include_all_helpers is on, the default), so in a typical app every controller below ApplicationController that calls helper or helper_method lists every module in app/helpers. Adding one helper module then rewrites all of those RBIs: in our app, about 50 files.

#225 (2021) went after the same churn by including everything through ApplicationHelper, and was closed as a draft. This takes a different approach, which doesn't depend on any module the app defines.

Implementation

When a controller's parent (the nearest superclass with its own HelperMethods) is a class this compiler generates an RBI for, the controller's module includes the parent's HelperMethods and then only the modules it adds, in the same order as at runtime. Method resolution doesn't change: the modules it no longer lists are ancestors of the parent's module.

A direct subclass of ActionController::Base still lists every module, because the gem RBI for ActionController::Base::HelperMethods can't know the helpers that other gems add to it at runtime.

The parent is found from the class chain rather than from gather_constants, which tapioca dsl SomeController narrows to the requested constants. That keeps tapioca dsl UserController and tapioca dsl generating the same RBI. (Our first version of this, a custom compiler in our app, checked gather_constants and re-listed every module on single-constant runs.)

Tests

  • The abstract ApplicationController test's expectation changes: UserController no longer repeats ::ActionController::Base::HelperMethods.
  • New: a controller whose parent has no helpers of its own includes its grandparent's module and only the module it adds, not one the grandparent already includes.
  • New: the same RBI when only the subclass is requested.

The manual page gets an example.

…ts helpers

A controller's `HelperMethods` includes its parent controller's module, and
the compiler listed every module from that chain again in each controller's
RBI. Rails calls `helper :all` on each direct subclass of
`ActionController::Base` (`include_all_helpers`, on by default), so every
controller below `ApplicationController` that has helpers of its own lists
every module in app/helpers, and adding one helper module rewrites all of
their RBIs.

When the parent's module is one this compiler generates an RBI for, include
it and only the modules the controller adds. A direct subclass of
`ActionController::Base` still lists every module, because the gem RBI for
`ActionController::Base::HelperMethods` can't know the helpers other gems add
to it at runtime.

The parent is found from the class chain, not from the gathered constants, so
`tapioca dsl UserController` generates the same RBI as `tapioca dsl`.

This branch has not been deployed

No deployments
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