Есть ли способ, которым вы можете получить коллекцию всех моделей в вашем приложении Rails?
В основном, я могу сделать, как: -
Models.each do |model|
puts model.class.name
end
Есть ли способ, которым вы можете получить коллекцию всех моделей в вашем приложении Rails?
В основном, я могу сделать, как: -
Models.each do |model|
puts model.class.name
end
Ответы:
РЕДАКТИРОВАТЬ: Посмотрите на комментарии и другие ответы. Есть более умные ответы, чем этот! Или попробуйте улучшить это как сообщество вики.
Модели не регистрируются в главном объекте, поэтому в Rails нет списка моделей.
Но вы все равно можете посмотреть содержимое каталога моделей вашего приложения ...
РЕДАКТИРОВАТЬ: Другой (дикой) идеей было бы использовать отражение Ruby для поиска всех классов, которые расширяют ActiveRecord :: Base. Не знаю, как вы можете перечислить все классы, хотя ...
РЕДАКТИРОВАТЬ: просто для удовольствия, я нашел способ перечислить все классы
РЕДАКТИРОВАТЬ: наконец удалось перечислить все модели, не глядя на каталоги
Если вы хотите обрабатывать и производный класс, вам нужно будет протестировать всю цепочку суперкласса. Я сделал это, добавив метод в класс Class:
источник
RAILS_ROOT
больше не доступен в Rails 3. Вместо этого используйтеDir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
, поэтому, если вы хотите загрузить все модели, вы можете легко их повторить - см. Мой ответ ниже.Полный ответ для Rails 3, 4 и 5:
Если
cache_classes
выключен (по умолчанию он выключен в разработке, но включен в работе):Затем:
Это гарантирует, что все модели в вашем приложении, независимо от того, где они находятся, загружены, и все используемые вами драгоценные камни, которые предоставляют модели, также загружены.
Это также должно работать с классами, которые наследуются
ActiveRecord::Base
, какApplicationRecord
в Rails 5, и возвращать только это поддерево потомков:Если вы хотите узнать больше о том, как это сделать, проверьте ActiveSupport :: DescendantsTracker .
источник
:environment
того,eager_load!
как она работаетRails.application.eager_load!
, вы можете просто загрузить модели:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
каталоги. Стремительная загрузка всего приложения - более полный ответ и гарантирует, что для определения моделей абсолютно не осталось места.Rails.application.paths["app/models"].eager_load!
На всякий случай, если кто-то наткнется на это, у меня есть другое решение, не полагаясь на чтение директории или расширение класса Class ...
Это вернет массив классов. Так что вы можете сделать
источник
ActiveRecord::Base.subclasses
но должны использоватьsend
? Кроме того, кажется, что вам нужно «дотронуться» до того, как модель появится, например,c = Category.new
и она появится. В противном случае это не так.ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
перечислять их.вернется
Дополнительная информация Если вы хотите вызвать метод для имени объекта без модели: строка неизвестный метод или переменные ошибки используйте это
источник
ActiveRecord::Base.send :subclasses
поиск имен таблиц - хорошая идея. Автоматическая генерация названий моделей может быть проблематичной, как уже упоминалось ранее..capitalize.singularize.camelize
можно заменить на.classify
.Я искал способы сделать это и в итоге выбрал этот путь:
источник: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
источник
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
некоторые из моделей могут быть не активированы, поэтому вам нужно их спасти.model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
Для Rails5 моделей теперь подклассы из
ApplicationRecord
так , чтобы получить список всех моделей в вашем приложении вы делаете:Или короче:
Если вы находитесь в режиме разработки, вам нужно будет загрузить модели до:
источник
Я думаю, что решение @ hnovick будет классным, если у вас нет моделей без таблиц. Это решение будет работать и в режиме разработки
Мой подход немного отличается, хотя -
Классифицировать хорошо должно дать вам имя класса из строки должным образом . safe_constantize гарантирует, что вы можете безопасно превратить его в класс без исключения. Это необходимо, если у вас есть таблицы базы данных, которые не являются моделями. компактный, так что все нули в перечислении удаляются.
источник
safe_constantize
.Если вы хотите только имена классов:
Просто запустите его в консоли Rails, не более того. Удачи!
РЕДАКТИРОВАТЬ: @ sj26 правильно, вам нужно сначала запустить это, прежде чем вы можете вызвать потомков:
источник
map
сputs
? Я не понимаю, точка должна бытьActiveRecord::Base.descendants.map(&:model_name)
Кажется, это работает для меня:
Rails загружает модели только тогда, когда они используются, поэтому для строки Dir.glob «требуются» все файлы в каталоге моделей.
Когда у вас есть модели в массиве, вы можете делать то, что думали (например, в представлении кода):
источник
...'/app/models/**/*.rb'
На одной строке:
Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
источник
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
источник
Всего в одной строке:
источник
Rails.application.eager_load!
перед выполнением в режиме разработки.Я пока не могу комментировать, но я думаю, что ответ sj26 должен быть лучшим ответом. Просто подсказка:
источник
С Rails 6 , Zetiwerk стал код по умолчанию Загрузчик.
Для быстрой загрузки попробуйте:
затем
источник
Да, есть много способов найти все названия моделей, но то, что я сделал в моем gem model_info , это даст вам все модели, даже включенные в gem .
затем просто распечатайте это
источник
Это работает для Rails 3.2.18
источник
Чтобы избежать предварительной загрузки всех Rails, вы можете сделать это:
require_dependency (f) - это то же самое, что
Rails.application.eager_load!
использует. Это должно избежать уже требуемых ошибок файла.Затем вы можете использовать все виды решений для перечисления моделей AR, например,
ActiveRecord::Base.descendants
источник
источник
Вот решение, которое было проверено со сложным приложением Rails (один квадратный)
Он берет лучшие части ответов в этой теме и объединяет их в самое простое и полное решение. Это обрабатывает случаи, когда ваши модели находятся в подкаталогах, используют set_table_name и т. Д.
источник
Только что наткнулся на эту, так как мне нужно напечатать все модели с их атрибутами (основано на комментарии @Aditya Sanghi):
источник
Это сработало для меня. Отдельное спасибо всем постам выше. Это должно вернуть коллекцию всех ваших моделей.
источник
В
Rails
реализующий методdescendants
, но модели не обязательно когда - нибудь наследуетActiveRecord::Base
, например, класс , который включает в себя модульActiveModel::Model
будет иметь такое же поведение , как модель, просто не будет связан с таблицей.Таким образом, в дополнение к тому, что говорят коллеги выше, малейшее усилие сделало бы это:
Накидка Обезьяны класса
Class
Рубин:и метод
models
, включая предков, как этот:Метод
Module.constants
возвращает (поверхностно) коллекциюsymbols
вместо констант, поэтому методArray#select
может быть заменен, как эта обезьяна-патчModule
:Обезьянье пятно
String
.И, наконец, метод моделей
источник
Это даст вам все классы моделей, которые есть в вашем проекте.
источник
источник
Я безуспешно перепробовал многие из этих ответов в Rails 4 (вау, они поменяли одну или две вещи, ради бога), я решил добавить свои. Те, которые вызывали ActiveRecord :: Base.connection и извлекали имена таблиц, работали, но не получили желаемый результат, потому что я спрятал некоторые модели (в папке внутри app / models /), которые я не хотел Удалить:
Я помещаю это в инициализатор и могу вызвать его из любого места. Предотвращает ненужное использование мыши.
источник
можете проверить это
источник
Предполагая, что все модели находятся в приложении / модели, и у вас есть grep & awk на вашем сервере (в большинстве случаев),
Это быстрее
Rails.application.eager_load!
или циклически просматривает каждый файлDir
.РЕДАКТИРОВАТЬ:
Недостатком этого метода является то, что он пропускает модели, которые косвенно наследуются от ActiveRecord (например
FictionalBook < Book
). Самый верный способ -Rails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
хоть и медленный.источник
Я просто привожу этот пример здесь, если кто-нибудь найдет его полезным. Решение основано на этом ответе https://stackoverflow.com/a/10712838/473040 .
Допустим, у вас есть столбец,
public_uid
который используется в качестве основного идентификатора для внешнего мира (вы можете найти причины, почему вы хотели бы сделать это здесь )Теперь допустим, что вы ввели это поле для множества существующих моделей, и теперь вы хотите восстановить все записи, которые еще не установлены. Вы можете сделать это так
теперь вы можете бежать
rake di:public_uids:generate
источник