I use the following line in an initializer to autoload code in my /lib
directory during development:
config/initializers/custom.rb:
RELOAD_LIBS = Dir[Rails.root + \'lib/**/*.rb\'] if Rails.env.development?
(from Rails 3 Quicktip: Auto reload lib folders in development mode)
It works great, but it\'s too inefficient to use in production- Instead of loading libs on each request, I just want to load them on start up. The same blog has another article describing how to do this:
config/application.rb:
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir[\"#{config.root}/lib/**/\"]
However, when I switch to that, even in development, I get NoMethodErrors when trying to use the lib functions.
Example of one of my lib files:
lib/extensions.rb:
Time.class_eval do
def self.milli_stamp
Time.now.strftime(\'%Y%m%d%H%M%S%L\').to_i
end
end
Calling Time.milli_stamp
will throw NoMethodError
I realize others have answered similar questions on SO but they all seem to deal with naming conventions and other issues that I didn\'t to have to worry about before- My lib classes already worked for per-request loading, I just want to change it to per-startup loading. What\'s the right way to do this?
I think this may solve your problem:
in config/application.rb:
config.autoload_paths << Rails.root.join(\'lib\')
and keep the right naming convention in lib.
in lib/foo.rb:
class Foo
end
in lib/foo/bar.rb:
class Foo::Bar
end
if you really wanna do some monkey patches in file like lib/extensions.rb, you may manually require it:
in config/initializers/require.rb:
require \"#{Rails.root}/lib/extensions\"
P.S.
Rails 3 Autoload Modules/Classes by Bill Harding.
And to understand what does Rails exactly do about auto-loading?
read Rails autoloading — how it works, and when it doesn\'t by Simon Coffey.
Though this does not directly answer the question, but I think it is a good alternative to avoid the question altogether.
To avoid all the autoload_paths
or eager_load_paths
hassle, create a \"lib\" or a \"misc\" directory under \"app\" directory. Place codes as you would normally do in there, and Rails will load files just like how it will load (and reload) model files.
This might help someone like me that finds this answer when searching for solutions to how Rails handles the class loading ... I found that I had to define a module
whose name matched my filename appropriately, rather than just defining a class:
In file lib/development_mail_interceptor.rb (Yes, I\'m using code from a Railscast :))
module DevelopmentMailInterceptor
class DevelopmentMailInterceptor
def self.delivering_email(message)
message.subject = \"intercepted for: #{message.to} #{message.subject}\"
message.to = \"myemail@mydomain.org\"
end
end
end
works, but it doesn\'t load if I hadn\'t put the class inside a module.
Use config.to_prepare to load you monkey patches/extensions for every request in development mode.
config.to_prepare do |action_dispatcher|
# More importantly, will run upon every request in development, but only once (during boot-up) in production and test.
Rails.logger.info \"\\n--- Loading extensions for #{self.class} \"
Dir.glob(\"#{Rails.root}/lib/extensions/**/*.rb\").sort.each do |entry|
Rails.logger.info \"Loading extension(s): #{entry}\"
require_dependency \"#{entry}\"
end
Rails.logger.info \"--- Loaded extensions for #{self.class}\\n\"
end