RoR:MyModel.descendants在第一次调用后在视图中返回[]?

时间:2011-05-04 18:38:55

标签: ruby-on-rails-3 activerecord

我想在视图中显示MyModel子类的选择列表。它还没有工作,所以对于健全性检查,我把它包括在我的观点中:

<%= MyModel.descendants %>

第一次时间我重新启动服务器后呈现此页面,它显示了后代列表(有六个)。所有后续次,它显示为空列表[]

FWIW,我的初始化程序中有require语句:

Dir[Rails.root.join("app/models/my_models/**/*.rb").to_s].each {|f| require f}

......我已经确认他们已经被要求了。

@($%&amp;是怎么回事?

3 个答案:

答案 0 :(得分:9)

我遇到了同样的问题。通过添加config/initializers/preload_models.rb来解决此问题:

Dir[Rails.root + 'app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }

希望能帮助某人。

答案 1 :(得分:7)

当您使用require时,即使重新加载my_model.rb,内核也不会要求您的子类.rb文件,因为它们已经被加载。你必须通过rails autoload。

基本上,在您第一次请求时,rails会从MyModel自动加载my_model.rb,然后需要my_models/sub_model.rbSubModel类继承MyModel,填充descendants数组。 但是,在您的以下请求中,rails再次自动加载MyModel(嘿,您处于开发模式),然后再次需要my_models/sub_model.rb。但是这一次,内核知道它已经加载了这个文件,并且不会再加载它。

我在一小时前遇到了这个问题,这引导我找到了你的帖子,并找到了解决方案。我们需要的是每次调用主类时都要自动加载子类。

这是一个解决方案:

class MyModel
  Dir[File.join(File.dirname(__FILE__),"my_models","*.rb")].each do |f|
    MyModels.const_get(File.basename(f,'.rb').classify)
  end
end

这些行可能会被放在课堂之外。如果您只有my_models中的文件而不是子目录中的文件,那应该足够了(对我而言)。如果你有一些(例如MyModels::Car::Ford,你可能需要在子模块中放置相同类型的东西(在my_models/car.rb中)。

答案 2 :(得分:7)

我刚刚在每个环境中启用了热切加载:

config.eager_load = true

即使为类名使用名称空间,这对我也有用。