Ruby-on-rails 无需创建子模块即可将模型构建到子文件夹中的优雅方式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1445341/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Elegant way to structure models into subfolders without creating submodules
提问by seb
I have numerous models in my app/models folder. I'd like to clean this folder up a little bit. Move models that belong to each other in subfolders. The problem is that by convention the model class is namespaced into an according module.
我的 app/models 文件夹中有很多模型。我想稍微清理一下这个文件夹。在子文件夹中移动属于彼此的模型。问题是按照惯例,模型类被命名为相应的模块。
E.g.
例如
app/models/blog/post.rb
app/models/blog/comment.rb
app/models/user.rb
app/models/blog/post.rb
app/models/blog/comment.rb
app/models/user.rb
so that:
以便:
app/models/blog/post.rb
应用程序/模型/博客/post.rb
class Post < ActiveRecord
end
and not
并不是
class Blog::Post < ActiveRecord
end
回答by Ion Br.
Here is what I used for Rails 3:
这是我用于 Rails 3 的内容:
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
This configuration tells Rails to scan all the app/models subfolders recursively and load all found models. No namespacing required.
此配置告诉 Rails 递归扫描所有 app/models 子文件夹并加载所有找到的模型。不需要命名空间。
回答by Tilendor
We needed to do this, and there is a very simple way.
我们需要这样做,有一个非常简单的方法。
move your models into the sub-folders, and then tell rails to load files from all subfolders in your environment.rb file:
将您的模型移动到子文件夹中,然后告诉 rails 从您的 environment.rb 文件中的所有子文件夹加载文件:
config.load_paths += Dir["#{RAILS_ROOT}/app/models/*"].find_all { |f| File.stat(f).directory? }
No namespacing required, and the models can be referred to as normal in your app
不需要命名空间,模型可以在您的应用程序中正常引用
回答by pickwick
I also created subfolders, and then added the following to the application.rb file:
我还创建了子文件夹,然后将以下内容添加到 application.rb 文件中:
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
But doing this alone isn't enough when subfolders are named using the same name as a model (e.g., a folder 'user' containing several files, one of which is 'user'). This was causing all kinds of errors in my code until I found that it could be solved by simply giving the folders names that are different from the models (e.g., 'user models') they contain. I found the suggestion at http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/, which actually points to this question.
但是,当子文件夹使用与模型相同的名称命名时(例如,包含多个文件的文件夹“user”,其中一个是“user”),仅执行此操作是不够的。这在我的代码中导致了各种错误,直到我发现它可以通过简单地提供与它们包含的模型(例如,“用户模型”)不同的文件夹名称来解决。我在http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/找到了这个建议,它实际上指向了这个问题。
回答by Aaron Gibralter
So I used to have in Rails 2 something like this:
所以我曾经在 Rails 2 中有这样的事情:
config.autoload_paths += Dir["#{config.root}/app/models/**/"]
And the following files:
以及以下文件:
- app/models/user/base.rb:
class User::Base - app/models/user/admin.rb:
class User::Admin
- 应用程序/模型/用户/base.rb:
class User::Base - 应用程序/模型/用户/admin.rb:
class User::Admin
When I upgraded to Rails 3, I kept getting an error along these lines: Expected .../app/models/user/foo.rb to define Foo. This clearly seemed crazy since Rails 2 automatically assumed that what you put in user/foo.rb would be User::Foonot just Foo.
当我升级到Rails 3中,我不停地沿着这些线路得到一个错误:Expected .../app/models/user/foo.rb to define Foo。这显然看起来很疯狂,因为 Rails 2 自动假设您放入 user/foo.rb 的内容User::Foo不仅仅是Foo.
So the way I ended up solving this was getting rid of model subdirectories in autoload_pathsand doing something like this:
所以我最终解决这个问题的方法是摆脱模型子目录autoload_paths并做这样的事情:
I created app/models/user.rb with:
我创建了 app/models/user.rb :
module User
autoload :User, 'user/base'
autoload :User, 'user/admin'
end
回答by Tim Zaripov
In my Rails 3.2.3 app, after i moved some models to subdirectories, i have stumbled into errors like
在我的 Rails 3.2.3 应用程序中,将一些模型移动到子目录后,我偶然发现了类似的错误
Expected /.../.../app/models/project/project_category.rb to define Project::ProjectCategory
for association calls (example: Project.first.project_category).
用于关联调用(例如:Project.first.project_category)。
In the end, the workaround i found was to set :class_name for every association to model in subdirectory...
最后,我发现的解决方法是为每个关联设置 :class_name 以在子目录中建模...
class Project < ActiveRecord::Base
belongs_to :project_category, :class_name => "::ProjectCategory"
end
"::" part here points to Rails that ProjectCategory model has no namespace, despite the fact that is defined in a 'models/project' subdirectory.
此处的“::”部分指向 Rails,即 ProjectCategory 模型没有命名空间,尽管它是在“models/project”子目录中定义的。
回答by chris_b
this version of Tilendor's solution works with Rails 3
此版本的 Tilendor 解决方案适用于 Rails 3
config.load_paths and RAILS_ROOT are deprecated in Rails 3, also you should put it in the config block of the config/application.rb, not environment.rb
config.load_paths 和 RAILS_ROOT 在 Rails 3 中被弃用,你也应该把它放在 config/application.rb 的配置块中,而不是 environment.rb
config.autoload_paths += Dir["#{Rails.root.to_s}/app/models/*"].find_all { |f| File.stat(f).directory? }
回答by Fellow Stranger
This worked for me in Rails 5.
这在 Rails 5 中对我有用。
Adding the following to application.rb
将以下内容添加到 application.rb
config.autoload_paths += Dir[ Rails.root.join('app/models/**/') ]
Beware though that you cannot have the same name on your folder as any of your models.
但请注意,您的文件夹中不能与任何模型具有相同的名称。
回答by Alessandra Pereyra
Maybe you could look upon RailsEngines. It's not exactly what you need, but could gave you some ideas.
也许你可以看看 RailsEngines。这不完全是你需要的,但可以给你一些想法。
Other than that, if your script seems to work fine (you could also just read all the files on each subfolder on model and require them), I don't see any problem against it.
除此之外,如果您的脚本似乎工作正常(您也可以读取模型上每个子文件夹中的所有文件并需要它们),我认为它没有任何问题。
回答by seb
Until I find a better solution I've created a init.rb in the app/models folder:
在找到更好的解决方案之前,我在 app/models 文件夹中创建了一个 init.rb:
app/models/init.rb
应用程序/模型/init.rb
%w[blog].each do |folder|
path = [File.dirname(__FILE__), folder, "*.rb"].join('/')
Dir[path].each {|file| require file }
end
Servers the purpose until now.
服务宗旨直到现在。
回答by Kangur
All the above answers didn't work for me. Somehow 'models' folder was loaded with subfolders, which resulted in 'Expected to contain ::.
以上所有答案对我都不起作用。不知何故,“模型”文件夹加载了子文件夹,导致“预期包含 ::”。
Most of my subdirs were STI classes so I've moved them to app/models_sti//*. Then all I needed to do was to put in application.rb
我的大部分子目录都是 STI 类,因此我已将它们移至 app/models_sti//*。然后我需要做的就是输入application.rb
#config.autoload_paths += Dir["#{Rails.root.to_s}/app/models/**/"]
# Loaded dynamically (cache_classes == false ?)
config.autoload_paths << Rails.root.join('app', 'models').to_s
config.autoload_paths += Dir["#{Rails.root.to_s}/app/models_sti/*"].find_all { |f| File.stat(f).directory? }
# Eager_load_paths - used only when cache_classes == true [rails spec says so]
config.eager_load_paths.delete_if do |path|
# If I didn't delete it from eager_load_paths I got errors even in develop
path == Rails.root.join('app', 'models_sti').to_s
end
config.eager_load_paths += config.autoload_paths

