I'm creating a new engine for a rails 3 application. As you can guess, this engine is in the lib directory of my application.
However, i have some problems developing it. Indeed, I need to restart my server each time I change something in the engine.
Is there a way to avoid this ?
Can I force rails to completely reload the lib directory or a specific file and his requirements for each request ?
Thanks for your help :)
I couldn't get any of the above to work for me so I dug in the Rails code a bit and came up with this:
New file: config/initializers/reload_lib.rb
if Rails.env == "development"
lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
Rails.application.reload_routes! # or do something better here
end
# For Rails 5.1+
ActiveSupport::Reloader.to_prepare do
lib_reloader.execute_if_updated
end
# For Rails pre-5.1
ActionDispatch::Callbacks.to_prepare do
lib_reloader.execute_if_updated
end
end
Yes, I know it's disgusting but it's a hack. There might be a better way to trigger a full reload, but this works for me. My specific use case was a Rack app mounted to a Rails route so I needed it to reload as I worked on it in development.
Basically what it does is it checks if any files in /lib have changed (modified timestamp) since last loaded and then triggers a reload if they change.
I might also mention I have this in my config/application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Which just by default makes sure everything in my lib directory gets loaded.
Yays!
TL;DR
put this in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
remove require
statements for your lib files
Go!
Let me explain in detail.
I don't know why this answer is accepted, since it doesn't help with reloading lib folder on each request. First I thought that it works for Rails 2, but the question clearly states that it was for Rails 3 and the release date of 3.0.0 is before the date of the answer.
Other answers seem over-complicated or don't provide a real solution.
I decided to investigate things a little, because it was bothering me and I've even found out that people have a workaround for this and it involves saving lib files inside app/models
in development and then moving it to /lib
when done. We can do better, right?
My solution is tested against:
Put this into your config/application.rb
:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"]
That's it!™
Make sure you put it here since it will not work if you put it in config/environments/development.rb
, for example.
Make sure your remove all the require
statements for your /lib
code since require
statements will also cause this solution to not work.
This code implicitly requires your code, so if you do environment checks (which are unnecessary) and instead of the above code, you decide to write something like this:
# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?
you should watch out on the old require
statements, since they are still required on all the non-development environments, in this scenario.
So if you still decide to do environment checks, make sure you do inverse checks for require statements. Otherwise you'll get bitten!
require "beer_creator" unless Rails.env.development?
You might think that writing entire paragraph about something that's unnecessary is also unnecessary, but I think that warning people about something that's necessary when doing something unnecessary is also necessary.
If you would like to know more about this topic, check out this little tutorial.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With