Подтвердить что ты не робот

Элегантный способ структурировать модели в подпапки без создания подмодулей

У меня есть множество моделей в папке моего приложения/моделей. Я хотел бы немного очистить эту папку. Перемещение моделей, которые принадлежат друг другу в подпапках. Проблема состоит в том, что по соглашению класс модели помещается в соответствующий модуль.

например.

приложение/модели/блог/post.rb
приложение/модели/блог/comment.rb
приложение/модели/user.rb

чтобы:

приложение/модели/блог/post.rb

class Post < ActiveRecord
end

а не

class Blog::Post < ActiveRecord
end
4b9b3361

Ответ 1

Вот что я использовал для Rails 3:

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

В этой конфигурации Rails сканирует все подпапки приложений/моделей рекурсивно и загружает все найденные модели. Не требуется пространство имен.

Ответ 2

Нам нужно было сделать это, и есть очень простой способ.

переместите свои модели в подпапки, а затем скажите рельсам на загрузку файлов из всех подпапок в файле environment.rb:

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

Нет необходимости в расширении имен, и модели могут быть названы обычными в вашем приложении.

Ответ 3

Я также создал подпапки, а затем добавил в файл application.rb следующее:

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

Но делать это самостоятельно недостаточно, когда имена подпапок называются с использованием того же имени, что и модель (например, папка "пользователь", содержащая несколько файлов, одна из которых является "пользователем" ). Это вызывало всевозможные ошибки в моем коде, пока я не обнаружил, что это можно решить, просто указав имена папок, которые отличаются от моделей (например, "пользовательских моделей" ), которые они содержат. Я нашел предложение http://www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/, что фактически указывает на этот вопрос.

Ответ 4

Итак, у меня в 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 и сделал что-то вроде этого:

Я создал приложение /models/user.rb с помощью:

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

Ответ 5

Возможно, вы могли бы взглянуть на RailsEngines. Это не совсем то, что вам нужно, но может дать вам некоторые идеи.

Кроме того, если ваш script работает нормально (вы также можете просто прочитать все файлы в каждой подпапке на модели и потребовать их), я не вижу никаких проблем с этим.

Ответ 6

эта версия решения Tilendor работает с Rails 3

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? }

Ответ 7

В моем приложении 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'.

Ответ 8

Это работало для меня в Rails 5.

Добавление следующего к application.rb

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

Остерегайтесь того, что вы не можете иметь то же имя в своей папке, что и любая из ваших моделей.

Ответ 9

Пока я не найду лучшее решение, я создал 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

Показывает сервер цели.

Ответ 10

Все приведенные выше ответы не помогли мне. Какая-то папка "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