Reputation: 1723
Similar questions have been asked many times. However, I have slightly different scenario and I still to find a clean solution to the following problem while developing a Rails 3 app:
I have a ruby code located in a single file. This code is one module MyModule
which contains a bunch of classes. I can't modify this code because it's auto-generated by an external tool. The file name is my_module.rb
and it resides in the lib
folder. This is the usual place for a code which doesn't belong to the main web app. I made sure it is auto-loaded once I access MyModule in one of my app controllers by modifying config.autoload_paths
setting in application.rb
.
Now I need to re-open one of the classes in MyModule
. I created a separate file some_class.rb
where I put the following code:
class MyModule::SomeClass def some_new_method ... end end
My question is: what is the best place to put this code? And what should be the name of the file?
The things I tried:
initializers
folder. it works fine in production environment. However, it breaks in development
because the code in initiliazers
folder is loaded once when the server starts up and lib
is reloaded on each request. So, the first request in development works fine, however, the subsequent requests fail. Also I don't like placing the code into initializers
because it's not really initialization piece but rather a part of business logic.lib
folder also doesn't work. It's not loaded. Only my_module.rb
is.lib
or some other folder under app
and then explicitly requir
ing it in controllers. Again it works in production but fails in development for the same reason aforementioned in case #1.my_module.rb
and some_class.rb
into lib
folder and require
ed them in an initializer. I think this is the best approach. The downside is that I still have to create a custom initializer and the code is not loaded lazily.UPDATE:
5. Thanks to raggi's suggestion, with auto-loading switched on, I put require_dependency 'some_class'
in my controller. In this case some_class.rb
is loaded on each request in development mode. This is my preferred approach . However, it still requires some sort of require
:)
Remember that files in lib
folder are auto-loaded lazily. Rails checks the folder only when you use modules or classes that rails can't find. The file name must follow the naming convention, hence the name my_module.rb
.
I wonder if there is a solution when both files are auto-loaded lazily without any require
statements.
Upvotes: 2
Views: 719
Reputation: 160271
TL;DR: Hide the require
outside of your mainline code.
I ran in to a similar problem when trying to create a validator within a module during development. I ran across this blog entry when I was trying to solve what sounds like the same problem.
// Added to application.rb
Rails::Application.config.autoload_paths.each do |d|
Dir["#{d}/*.rb"].each do |p|
puts "Requiring '#{p}' on startup..."
require p
end
end
Upvotes: 0
Reputation: 1297
Did you try require_dependency in your controller instead of require?
Upvotes: 1
Reputation: 18765
You can put the files in the lib directory and have them not lazily loaded but autoloaded, in config/application.rb if you want to put files in different subfolders:
config.autoload_paths += Dir["#{config.root}/lib/**/"]
Or if you need only the lib folder:
config.autoload_paths += %W(#{config.root}/lib)
Upvotes: 0