This file contains 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
~/action_dispatch/middleware/callbacks.rb has following code | |
def call(env) | |
_run_call_callbacks do | |
_run_prepare_callbacks if @prepare_each_request | |
@app.call(env) | |
end | |
end | |
def self.after(*args, &block) | |
set_callback(:call, :after, *args, &block) | |
end | |
~/rails/application/bootstrap.rb has following code | |
initializer :set_clear_dependencies_hook do | |
unless config.cache_classes | |
ActionDispatch::Callbacks.after do | |
ActiveSupport::DescendantsTracker.clear | |
ActiveSupport::Dependencies.clear | |
end | |
end | |
end | |
~/active_record/railtie.rb has following code | |
config.after_initialize do | |
ActiveSupport.on_load(:active_record) do | |
instantiate_observers | |
ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do | |
ActiveRecord::Base.instantiate_observers | |
end | |
end | |
end | |
All the above mentioned code does something like this. | |
When the app is served then there is an after callback which clears all | |
the dependencies. | |
Let's say I have UserObserver . This observer will ensure that User is | |
loaded and proper before_save/after_save callbacks are attached to | |
this class so that observer could be called. | |
Here is the code for reload | |
# reloads the environment | |
def reload!(print=true) | |
puts "Reloading..." if print | |
# This triggers the to_prepare callbacks | |
ActionDispatch::Callbacks.new(Proc.new {}, false).call({}) | |
true | |
end | |
Notice that the app being passed is Proc.new {}. So when reload! is called | |
then UserObserver is loaded which loads User. Proper callbacks are set | |
on User and then app.call is done which does nothing. And then | |
Dependencies.clear is called which clears the User. Now when | |
you load User then User gets loaded but this User does not have the | |
observer hooks baked into it. | |
So why does this issue come up in reload! and not when console is | |
loaded the first time. | |
When console is loaded firs time then app.call never happens. In that | |
case @app.load_console is executed. Here @app is Rails.application. | |
When reload! is called then full lifecycle is executed and part of lifecycle | |
is calling Dependencies.clear. | |
What is the fix? | |
I don't really know. I changed code from this | |
def reload!(print=true) | |
puts "Reloading..." if print | |
#ActionDispatch::Callbacks.new(Proc.new {}, false).call({}) | |
true | |
end | |
to | |
def reload!(print=true) | |
puts "Reloading..." if print | |
Rails::Console.start(Rails.application) | |
true | |
end | |
and everything works. The only issue is that everytime | |
you do reload! you are nesting into a new IRB console so you | |
need to do more than one exit to get out of console. | |
Not a good fix. May be JV or someone else will have better solution. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment