我在初始化程序中使用以下行在开发期间在/lib
目录中自动加载代码:
config / initializers / custom.rb:
RELOAD_LIBS = Dir[Rails.root + 'lib/**/*.rb'] if Rails.env.development?
(来自Rails 3 Quicktip: Auto reload lib folders in development mode)
它运行良好,但在生产中使用效率太低 - 而不是在每个请求上加载库,我只想在启动时加载它们。同一博客有another article描述如何执行此操作:
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/**/"]
然而,当我切换到那个时,即使在开发中,我在尝试使用lib函数时也会得到NoMethodErrors。
我的一个lib文件示例:
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
调用Time.milli_stamp
会抛出NoMethodError
我意识到其他人已经在SO上回答了类似的问题,但他们似乎都在处理命名约定和其他我以前不必担心的问题 - 我的lib类已经工作 for per -request加载,我只想将其更改为per- startup 加载。什么是正确的方法?
答案 0 :(得分:543)
我认为这可以解决您的问题:
config.autoload_paths << Rails.root.join('lib')
并在 lib 中保留正确的命名约定。
lib / foo.rb 中的:
class Foo
end
lib / foo / bar.rb 中的:
class Foo::Bar
end
如果你真的想在 lib / extensions.rb 这样的文件中做一些猴子补丁,你可以手动要求它:
config / initializers / require.rb :
require "#{Rails.root}/lib/extensions"
P.S。
了解Rails对自动加载的确切做法是什么? 阅读Simon Coffey撰写的Rails autoloading — how it works, and when it doesn't。
答案 1 :(得分:33)
虽然这并没有直接回答这个问题,但我认为这是完全避免这个问题的一个很好的选择。
要避免所有autoload_paths
或eager_load_paths
麻烦,请创建一个&#34; lib&#34;或者&#34; misc&#34;目录下&#34; app&#34;目录。像往常一样放置代码,Rails将加载文件,就像加载(和重新加载)模型文件一样。
答案 2 :(得分:6)
这可能会帮助像我一样的人在搜索Rails如何处理类加载的解决方案时找到答案...我发现我必须定义一个module
,其名称与我的文件名相匹配,而不仅仅是定义一个类:
在文件 lib / development_mail_interceptor.rb (是的,我正在使用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
有效,但如果我没有把类放在模块中,它就不会加载。
答案 3 :(得分:0)
使用config.to_prepare为开发模式中的每个请求加载猴子补丁/扩展。
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"
端