3

我使用Alex Reisner 博客文章中的一些技巧在我的一个模型中实现了 STI 。我已经让我的所有子类都使用超类的控制器,并使用序列化/存储来保存额外的属性。我将model_nameandself.select_options方法添加到超类中,并从 Alex 的博客中添加了预加载初始化程序。我还更改了我collection_select在 _form 视图助手和属性验证中的使用self.select_options方法。我所有的子类都在 app/models/subfolder 中的单个文件中,尽管它们不像 SubFolder::Subclass 那样命名空间。

然后我开始遇到问题。更改任何代码后,self.select_options停止返回所有子类。它只返回一个小子集或不返回。因此,由于验证和 _form 绑定,我无法在代码更改后编辑/更新我的模型。据我所知,当我更改任何代码时,Rails 会重新加载环境,但不会重新加载子文件夹中的模型。

我尝试像许多建议一样将路由添加到 config.autoload_paths ,但最终没有奏效。

所以最终,我想要:

  • 修复自动加载的东西,所以我不必在每次更改后重新启动服务器
  • 基于包含所有子目录的子目录,以避免手动维护数组
  • Rails 3.2.11,红宝石 1.9.3p125,ubuntu 12.04.01,rvm
4

2 回答 2

3

我最终将这个答案中的代码和这个答案代码和从底部的精彩博客文章中收集到的知识结合起来。config.autoload_paths似乎从来没有帮助任何东西,但我把它们留在那里。关键部分是初始化程序,它在启动时需要子目录中的所有文件,然后在每次重新加载时。我试load了一遍require_dependency,还是不行。不必一直重新加载绝对是一件好事。

在应用程序.rb

config.autoload_paths += %W(#{config.root}/app/models/configuration)

开发中.rb

config.autoload_paths += Dir["#{config.root}/app/models/configuration/**"]

在 preload_sti_models.rb

if Rails.env.development?
  Dir.entries("#{Rails.root}/app/models/subfolder").each do |c|
    require_dependency File.join("app","models", "subfolder", "#{c}") if c =~ /.rb$/
  end
  ActionDispatch::Reloader.to_prepare do
    Dir.entries("#{Rails.root}/app/models/subfolder").each do |c|
      require_dependency File.join("app","models", "subfolder", "#{c}") if c =~ /.rb$/
    end
  end
end

一些包含有用信息的博客文章

  1. http://wondible.com/2012/01/13/rails-3-2-autoloading-in-theory/
  2. http://wondible.com/2011/12/30/rails-autoloading-cleaning-up-the-mess/
  3. http://wondible.com/2011/12/23/give-rails-autoloading-a-boot-to-the-head/
  4. http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

编辑:这是众所周知的事情

于 2013-02-05T15:54:24.363 回答
1

这个解决方案类似于上面的 undefinedvariable,但更 DRY。

# organize your sti classes in directories named after the parent
sti_directory_paths = [
  Rails.root.join("app","models","subfolder_one"),
  Rails.root.join("app","models","subfolder_two"),
]

def require_sti_model(path, filename)
  require_dependency (path + filename).to_s
end

# if you use something like guard, just exclude from production
unless Rails.env.production?
  sti_directory_paths.each do |sti_directory_path|
    Dir[sti_directory_path + "*.rb"].each do |filename|
      require_sti_model(sti_directory_path, filename)
      ActionDispatch::Reloader.to_prepare do
        require_sti_model(sti_directory_path, filename)
      end
    end
  end
end
于 2013-08-11T16:37:38.327 回答