繁体   English   中英

Rails:将模型结构化为子文件夹而不创建子模块的优雅方式

[英]Rails: Elegant way to structure models into subfolders without creating submodules

我的app / models文件夹中有很多模型。 我想稍微清理一下这个文件夹。 在子文件夹中移动彼此属于的模型。 问题是按照惯例,模型类被命名为相应的模块。

例如

应用程序/模型/博客/ post.rb
应用程序/模型/博客/ comment.rb
应用程序/模型/ user.rb

以便:

应用程序/模型/博客/ post.rb

class Post < ActiveRecord
end

并不是

class Blog::Post < ActiveRecord
end

这是我用于Rails 3的内容:

config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]

此配置告诉Rails递归扫描所有app / models子文件夹并加载所有找到的模型。 不需要命名空间。

我们需要这样做,而且有一种非常简单的方法。

将模型移动到子文件夹中,然后告诉rails从environment.rb文件中的所有子文件夹加载文件:

config.load_paths += Dir["#{RAILS_ROOT}/app/models/*"].find_all { |f| File.stat(f).directory? }

不需要命名空间,并且可以在您的应用中将模型称为正常模型

我还创建了子文件夹,然后将以下内容添加到application.rb文件中:

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

但是当使用与模型相同的名称命名子文件夹时(例如,包含多个文件的文件夹'user',其中一个是'user'),单独执行此操作是不够的。 这导致我的代码中出现各种错误,直到我发现它可以通过简单地给出与它们包含的模型(例如,“用户模型”)不同的文件夹名称来解决。 我在http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/找到了这个建议,这实际上指的是这个问题。

所以我以前在Rails 2中有这样的东西:

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

以下文件:

  • app / models / user / base.rb: class User::Base
  • app / models / user / admin.rb: class User::Admin

当我升级到Rails 3时,我不断遇到错误: Expected .../app/models/user/foo.rb to define Foo 这显然看起来很疯狂,因为Rails 2自动假设你在user / foo.rb中输入的内容是User::Foo而不仅仅是Foo

所以我最终解决这个问题的方法是在autoload_paths删除模型子目录并执行以下操作:

我创建了app / models / user.rb:

module User
  autoload :User, 'user/base'
  autoload :User, 'user/admin'
end

在我的Rails 3.2.3应用程序中,在我将一些模型移动到子目录之后,我偶然发现了错误

Expected /.../.../app/models/project/project_category.rb to define Project::ProjectCategory

用于关联调用(例如:Project.first.project_category)。

最后,我找到的解决方法是为每个在子目录中建模的关联设置:class_name ...

class Project < ActiveRecord::Base

  belongs_to :project_category, :class_name => "::ProjectCategory"

end

“::”部分指向Rails,ProjectCategory模型没有命名空间,尽管事实是在'models / project'子目录中定义的。

也许你可以看看RailsEngines。 这不完全是你需要的,但可以给你一些想法。

除此之外,如果您的脚本似乎工作正常(您也可以只读取模型上每个子文件夹上的所有文件并要求它们),我没有看到任何问题。

这在Rails 5中对我有用。

将以下内容添加到application.rb

config.autoload_paths += Dir[ Rails.root.join('app/models/**/') ]

请注意,您的文件夹上的名称不能与任何型号相同。

这个版本的Tilendor解决方案适用于Rails 3

在Rails 3中不推荐使用config.load_paths和RAILS_ROOT,也应该将它放在config / application.rb的config块中,而不是environment.rb

config.autoload_paths += Dir["#{Rails.root.to_s}/app/models/*"].find_all { |f| File.stat(f).directory? }

在找到更好的解决方案之前,我在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

直到现在服务器的目的。

以上所有答案对我都不起作用。 不知何故'models'文件夹加载了子文件夹,导致'期望包含::。

我的大多数子目录都是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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM