6

我正在尝试编写一个定义 MongoMapper 模型的插件。问题是,当我运行时script/console,我收到此错误:

/home/helder/.rvm/gems/ruby-1.8.7-p249/gems/mongo_mapper-0.8.2/lib/mongo_mapper/connection.rb:29:in ``数据库':NameError:MongoMapper :: Connection中未初始化的类变量@@database_name

这让我认为它正在尝试在设置数据库连接之前加载我的插件模型。如何让它在我的应用程序代码的其余部分之后加载插件?

4

1 回答 1

11

我将尝试解决我遇到的错误以及标题中所述的一般问题。

具体错误

我弄清楚了问题所在。正如我在上面的评论中所说,问题在于 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)。享受。

于 2010-07-13T01:29:10.567 回答