Repository navigation
Include the parent controller's helper module instead of re-listing its helpers - #2760
Open
ndbroadbent wants to merge 1 commit into
Open
ndbroadbent wants to merge 1 commit into
ndbroadbent wants to merge 1 commit into
Conversation
…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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Each controller's generated
HelperMethodslists every module in its ancestor chain, including all of its parent controller's. Rails callshelper :allon each direct subclass ofActionController::Base(wheninclude_all_helpersis on, the default), so in a typical app every controller belowApplicationControllerthat callshelperorhelper_methodlists every module inapp/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'sHelperMethodsand 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::Basestill lists every module, because the gem RBI forActionController::Base::HelperMethodscan'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, whichtapioca dsl SomeControllernarrows to the requested constants. That keepstapioca dsl UserControllerandtapioca dslgenerating the same RBI. (Our first version of this, a custom compiler in our app, checkedgather_constantsand re-listed every module on single-constant runs.)Tests
ApplicationControllertest's expectation changes:UserControllerno longer repeats::ActionController::Base::HelperMethods.The manual page gets an example.