我将尝试解决我遇到的错误以及标题中所述的一般问题。
具体错误
我弄清楚了问题所在。正如我在上面的评论中所说,问题在于 Rails (2.3.8) 在使用 ActiveRecord 时,首先设置数据库连接,然后加载 gems,然后加载插件(按此顺序)。因此,如果您有任何插件需要在初始化期间访问数据库(即,在插件init.rb
或其他文件require
中),一切正常。
但是当使用 MongoMapper 时,Rails 将 MongoMapper 的类与所有其他 gem/插件一起加载,但不建立它的连接(Rails 不这样做,插件本身也不会触发)。目前在MongoDB 的文档中推荐的方式是创建一个像这样的初始化程序:
MongoMapper.connection = Mongo::Connection.new('localhost', 27017)
MongoMapper.database = "#myapp-#{Rails.env}"
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
MongoMapper.connection.connect_to_master if forked
end
end
但是由于插件是在文件运行之前初始化config/initializers
的,如果你尝试定义一个 MongoMapper 模型,一旦它得到一个访问数据库的调用(比如对key
类方法的调用),BOOM。你得到问题中引用的错误。
解决这个问题的一种方法是不需要在init.rb
需要数据库的文件中,而只是将它们添加到加载路径中(如果它们不在lib/
orapp/models
中,Rails 会自动添加到加载路径中)。这样,模型只会在require
被引用时被 Rails 的自动类加载器加载,这通常会在您的应用程序代码中。到那时,数据库连接已经建立。当然,这仅在您确实不需要在插件初始化期间引用这些类时才有效。否则,请继续阅读。
一般问题
如何让 Rails在初始化代码后加载插件?
在你的插件上init.rb
,抛出任何需要在这个块内等待的东西:
config.after_initialize do
# require my models
# do this
# do that
end
该config
变量与传递给文件Rails::Initializer.run
内部的块相同config/environment.rb
,并且由 Rails 提供给您的插件init.rb
,无需额外费用。
在所有内容完成加载并初始化之后,但在任何请求进入之前,您放入该块中的任何内容都将被执行(by Rails::Initializer#after_initialize
)。享受。