You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is not a new issue with Rails autoloading, but a challenge I feel when working with Engines (either developing engines as a gem maintainer or consuming engines as an application developer)
For example, an Engine may have a setup like this:
moduleGoodJobclassApplicationJob < ActiveJob::Base# some configurationActiveSupport.run_load_hooks(:good_job_application_job,self)endclassUtilityOneJob < ApplicationJob;endclassUtilityTwoJob < ApplicationJob;endclassUtilityThreeJob < ApplicationJob;end# ... and many moreend
I give an example of GoodJob, but this is a very analogous situation to other Engines with autoloaded classes/subclasses (models, controllers, etc.); for example Devise, which has a DeviseController (with load_hook) that is then subclassed with a desire to extend.
I want to be able to allow application developers to extend the subclasses, and I want to defer autoloaded constants as much as possible (ideally not touching Action Controller or Active Model at all until during initialization), and this seems like it should be reasonable:
# config/initializers/good_job.rbActiveSupport.on_load(:good_job_application_job)do# Customize a subclassGoodJob::UtilityJobOne.queue_name="something_custom"end
This usually works ok, except in the case when the UtilityJobOnebeing loaded causes ApplicationJob to be loaded for the very first time, in which case it raises a uninitialized constant UtilityJobOne (NameError). This is because of the autoloading chain:
GoodJob::UtilityJobOne first must load its parent class GoodJob::ApplicationJob for the first time, which triggers the load_hook which itself references UtilityOneJob which has not yet completed loading and thus a NameError 💥
There is what I consider a workaround for this which is to use inherited (which is triggered _after the subclass constant is loaded), but I find it somewhat complex and wonder if there is a better way, or whether this is something that should be turned into a hook pattern:
I realize that another solution as a engine maintainer is to add load hooks to every subclass, but that seems onerous, and as an application developer I'd have to convince other engine maintainers to do so (which is totally ok, so long as there isn't a better way I'm missing or a reasonable central interface for modifying autoloaded subclasses).
The text was updated successfully, but these errors were encountered:
This is not a new issue with Rails autoloading, but a challenge I feel when working with Engines (either developing engines as a gem maintainer or consuming engines as an application developer)
For example, an Engine may have a setup like this:
I give an example of GoodJob, but this is a very analogous situation to other Engines with autoloaded classes/subclasses (models, controllers, etc.); for example Devise, which has a
DeviseController
(with load_hook) that is then subclassed with a desire to extend.I want to be able to allow application developers to extend the subclasses, and I want to defer autoloaded constants as much as possible (ideally not touching Action Controller or Active Model at all until during initialization), and this seems like it should be reasonable:
This usually works ok, except in the case when the
UtilityJobOne
being loaded causes ApplicationJob to be loaded for the very first time, in which case it raises auninitialized constant UtilityJobOne (NameError)
. This is because of the autoloading chain:GoodJob::UtilityJobOne
first must load its parent classGoodJob::ApplicationJob
for the first time, which triggers the load_hook which itself referencesUtilityOneJob
which has not yet completed loading and thus aNameError
💥There is what I consider a workaround for this which is to use
inherited
(which is triggered _after the subclass constant is loaded), but I find it somewhat complex and wonder if there is a better way, or whether this is something that should be turned into a hook pattern:I realize that another solution as a engine maintainer is to add load hooks to every subclass, but that seems onerous, and as an application developer I'd have to convince other engine maintainers to do so (which is totally ok, so long as there isn't a better way I'm missing or a reasonable central interface for modifying autoloaded subclasses).
The text was updated successfully, but these errors were encountered: