我使用Alex Reisner's blog post中的一些提示在我的一个模型中实现了STI。我已经让所有子类都使用超类的控制器,使用serialize / store来保存额外的属性。我将model_name
和self.select_options
方法添加到超类中,并将预加载初始化程序添加到Alex的博客中。我还在_form视图助手和属性验证中更改了我的collection_select
以使用self.select_options
方法。我的所有子类都在app / models /子文件夹中的单个文件中,尽管它们不像SubFolder :: Subclass那样被命名空间。
然后我开始遇到问题。在更改任何代码后,self.select_options
将停止返回所有子类。它只返回一个小子集或没有。因此,由于验证和_form绑定,我无法在代码更改后编辑/更新我的模型。据我所知,当我更改任何代码时,Rails会重新加载环境,而不是子文件夹中的模型。
我尝试将路由添加到config.autoload_paths like many suggest,但最终还是没有用。
所以最终,我想:
答案 0 :(得分:3)
我最终合并了此answer和此one的代码以及从底部的wondible博客帖子收集的知识。 config.autoload_paths
似乎没有任何帮助,但我把它们留在那里。关键部分是初始化程序,它在启动时需要子目录中的所有文件,然后在每次重新加载时。我尝试load
而不是require_dependency
,但没有效果。无需一直重装,这绝对是一件好事。
在application.rb
中config.autoload_paths += %W(#{config.root}/app/models/configuration)
在development.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 :(得分: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