public
Last active

  • Download Gist
gistfile1.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
~/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.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.