App/modelsフォルダーに多数のモデルがあります。このフォルダを少し整理したいと思います。サブフォルダー内で互いに属するモデルを移動します。問題は、慣例により、モデルクラスが対応するモジュールに名前空間化されることです。
例えば。
app/models/blog/post.rb
app/models/blog/comment.rb
app/models/user.rb
そのため:
app/models/blog/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'、そのうちの1つは '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/**/"]
そして、次のファイル:
class User::Base
class User::Admin
Rails 3にアップグレードしたとき、次の行に沿ってエラーが発生し続けました:Expected .../app/models/user/foo.rb to define Foo
。Rails 2はuser/foo.rbに入れるものは、Foo
だけでなくUser::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
ここでの「::」の部分は、「models/project」サブディレクトリで定義されているという事実にもかかわらず、ProjectCategoryモデルには名前空間がないというRailsを指します。
たぶん、RailsEnginesを見ることができます。それはまさにあなたが必要とするものではありませんが、いくつかのアイデアを与えることができます。
それ以外は、スクリプトが正常に動作するようであれば(モデルの各サブフォルダーにあるすべてのファイルを読み取って必要な場合もあります)、それに対する問題は発生しません。
tilendorのこのバージョンのソリューションは、Rails 3
config.load_pathsとRails_ROOTは、Rails 3で非推奨になりました。また、environment.rbではなく、config/application.rbのconfigブロックに配置する必要があります
config.autoload_paths += Dir["#{Rails.root.to_s}/app/models/*"].find_all { |f| File.stat(f).directory? }
これはRails 5。
以下をapplication.rb
に追加します
config.autoload_paths += Dir[ Rails.root.join('app/models/**/') ]
ただし、フォルダにモデルと同じ名前を付けることはできません。
上記のすべての答えは私にはうまくいきませんでした。どういうわけか「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
より良い解決策が見つかるまで、app/modelsフォルダーにinit.rbを作成しました。
app/models/init.rb
%w[blog].each do |folder|
path = [File.dirname(__FILE__), folder, "*.rb"].join('/')
Dir[path].each {|file| require file }
end
これまでの目的を果たす。