Existe-t-il un moyen d'obtenir une collection de tous les modèles de votre application Rails?
Fondamentalement, puis-je faire des choses comme: -
Models.each do |model|
puts model.class.name
end
Existe-t-il un moyen d'obtenir une collection de tous les modèles de votre application Rails?
Fondamentalement, puis-je faire des choses comme: -
Models.each do |model|
puts model.class.name
end
Réponses:
EDIT: Regardez les commentaires et autres réponses. Il y a des réponses plus intelligentes que celle-ci! Ou essayez d'améliorer celui-ci en tant que wiki communautaire.
Les modèles ne s'enregistrent pas eux-mêmes dans un objet maître, donc non, Rails n'a pas la liste des modèles.
Mais vous pouvez toujours regarder dans le contenu du répertoire des modèles de votre application ...
EDIT: Une autre idée (sauvage) serait d'utiliser la réflexion Ruby pour rechercher toutes les classes qui étendent ActiveRecord :: Base. Je ne sais pas comment lister toutes les classes ...
EDIT: Juste pour le plaisir, j'ai trouvé un moyen de lister toutes les classes
EDIT: Enfin réussi à lister tous les modèles sans regarder les répertoires
Si vous souhaitez également gérer la classe dérivée, vous devrez tester l'ensemble de la chaîne de superclasse. Je l'ai fait en ajoutant une méthode à la classe Class:
la source
RAILS_ROOT
n'est plus disponible dans Rails 3. Au lieu de cela, utilisezDir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
maintenant, donc si vous avez hâte de charger tous les modèles, vous pouvez les itérer facilement - voir ma réponse ci-dessous.La réponse complète pour les rails 3, 4 et 5 est:
Si
cache_classes
est désactivé (par défaut, il est désactivé en développement, mais activé en production):Ensuite:
Cela garantit que tous les modèles de votre application, quel que soit leur emplacement, sont chargés et toutes les gemmes que vous utilisez qui fournissent des modèles sont également chargées.
Cela devrait également fonctionner sur les classes qui héritent de
ActiveRecord::Base
, commeApplicationRecord
dans Rails 5, et renvoyer uniquement ce sous-arbre de descendants:Si vous souhaitez en savoir plus sur la façon dont cela est fait, consultez ActiveSupport :: DescendantsTracker .
la source
:environment
dueager_load!
fonctionnement.Rails.application.eager_load!
, vous pouvez simplement charger les modèles:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
répertoires. Désireux de charger toute l'application est une réponse plus complète et vous assurera qu'il n'y a absolument plus de place pour les modèles à définir.Rails.application.paths["app/models"].eager_load!
Juste au cas où quelqu'un trébucherait sur celui-ci, j'ai une autre solution, ne pas compter sur la lecture de dir ou étendre la classe Class ...
Cela renverra un tableau de classes. Vous pouvez donc faire
la source
ActiveRecord::Base.subclasses
mais devez utilisersend
? De plus, il semble que vous devez "toucher" le modèle avant qu'il n'apparaisse, par exemplec = Category.new
et qu'il apparaisse. Sinon, ce ne sera pas le cas.ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
les énumérer.reviendra
Informations supplémentaires Si vous souhaitez appeler une méthode sur le nom de l'objet sans modèle: chaîne méthode inconnue ou erreurs de variable utilisez ceci
la source
ActiveRecord::Base.send :subclasses
- rechercher les noms de table est une bonne idée. La génération automatique des noms de modèle peut être problématique, comme indiqué précédemment..capitalize.singularize.camelize
peut être remplacé par.classify
.J'ai cherché des moyens de le faire et j'ai fini par choisir de cette façon:
source: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
la source
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Certains modèles peuvent ne pas être activés, vous devez donc le sauver.model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
Pour les modèles Rails5 sont maintenant des sous - classes de
ApplicationRecord
afin d'obtenir la liste de tous les modèles dans votre application, vous faites:Ou plus court:
Si vous êtes en mode dev, vous devrez charger les modèles avant:
la source
Je pense que la solution de @ hnovick est cool si vous n'avez pas de modèles sans table. Cette solution fonctionnerait également en mode développement
Mon approche est cependant subtilement différente -
classify est bien censé vous donner correctement le nom de la classe à partir d'une chaîne . safe_constantize garantit que vous pouvez le transformer en classe en toute sécurité sans lever d'exception. Cela est nécessaire si vous avez des tables de base de données qui ne sont pas des modèles. compact pour que tous les nils de l'énumération soient supprimés.
la source
safe_constantize
.Si vous voulez juste les noms de classe:
Il suffit de l'exécuter dans la console Rails, rien de plus. Bonne chance!
EDIT: @ sj26 a raison, vous devez d'abord l'exécuter avant de pouvoir appeler des descendants:
la source
map
avecputs
? Je ne comprends pas le point devrait êtreActiveRecord::Base.descendants.map(&:model_name)
Cela semble fonctionner pour moi:
Rails ne charge les modèles que lorsqu'ils sont utilisés, donc la ligne Dir.glob "nécessite" tous les fichiers du répertoire models.
Une fois que vous avez les modèles dans un tableau, vous pouvez faire ce que vous pensiez (par exemple dans le code de vue):
la source
...'/app/models/**/*.rb'
Sur une ligne:
Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
la source
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
la source
En une seule ligne:
la source
Rails.application.eager_load!
avant l'exécution en mode développement.Je ne peux pas encore commenter, mais je pense que la réponse sj26 devrait être la meilleure réponse. Juste un indice:
la source
Avec Rails 6 , Zetiwerk est devenu le chargeur de code par défaut.
Pour un chargement rapide, essayez:
ensuite
la source
Oui, il existe de nombreuses façons de trouver tous les noms de modèles, mais ce que j'ai fait dans ma gem model_info est, cela vous donnera tous les modèles même inclus dans les gemmes.
puis imprimez simplement ceci
la source
Cela fonctionne pour Rails 3.2.18
la source
Pour éviter de précharger tous les Rails, vous pouvez procéder comme suit:
require_dependency (f) est le même que celui
Rails.application.eager_load!
utilisé. Cela devrait éviter les erreurs de fichier déjà requises.Ensuite, vous pouvez utiliser toutes sortes de solutions pour répertorier les modèles AR, comme
ActiveRecord::Base.descendants
la source
la source
Voici une solution qui a été approuvée avec une application Rails complexe (celle qui alimente Square)
Il prend les meilleures parties des réponses dans ce fil et les combine dans la solution la plus simple et la plus approfondie. Cela gère les cas où vos modèles sont dans des sous-répertoires, utilisez set_table_name etc.
la source
Je viens de tomber sur celui-ci, car j'ai besoin d'imprimer tous les modèles avec leurs attributs (construits sur le commentaire de @Aditya Sanghi):
la source
Cela a fonctionné pour moi. Un merci spécial à tous les messages ci-dessus. Cela devrait renvoyer une collection de tous vos modèles.
la source
L'
Rails
implémente la méthodedescendants
, mais les modèles n'héritent pas nécessairement deActiveRecord::Base
, par exemple, la classe qui inclut le moduleActiveModel::Model
aura le même comportement qu'un modèle, mais ne sera pas liée à une table.Complétant ainsi ce que disent les collègues ci-dessus, le moindre effort ferait cela:
Patch de singe de la classe
Class
du Rubis:et la méthode
models
, y compris les ancêtres, comme ceci:La méthode
Module.constants
renvoie (superficiellement) une collection desymbols
, au lieu de constantes, donc, la méthodeArray#select
peut être substituée comme ce patch de singe deModule
:Patch de singe de
String
.Et enfin, la méthode des modèles
la source
Cela vous donnera toutes les classes de modèles que vous avez sur votre projet.
la source
la source
J'ai essayé tellement de ces réponses sans succès dans Rails 4 (wow ils ont changé une chose ou deux pour l'amour de Dieu) J'ai décidé d'ajouter la mienne. Ceux qui ont appelé ActiveRecord :: Base.connection et tiré les noms de table ont fonctionné mais n'ont pas obtenu le résultat que je voulais parce que j'ai caché certains modèles (dans un dossier à l'intérieur de l'application / models /) que je ne voulais pas supprimer:
Je mets cela dans un initialiseur et je peux l'appeler de n'importe où. Empêche l'utilisation inutile de la souris.
la source
peut vérifier cela
la source
En supposant que tous les modèles sont dans l'application / modèles et que vous avez grep & awk sur votre serveur (la majorité des cas),
C'est plus rapide que
Rails.application.eager_load!
ou en boucle dans chaque fichier avecDir
.ÉDITER:
L'inconvénient de cette méthode est qu'elle manque des modèles qui héritent indirectement d'ActiveRecord (par exemple
FictionalBook < Book
). Le moyen le plus sûr estRails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, même si c'est un peu lent.la source
Je lance juste cet exemple ici si quelqu'un le trouve utile. La solution est basée sur cette réponse https://stackoverflow.com/a/10712838/473040 .
Supposons que vous ayez une colonne
public_uid
utilisée comme ID principal pour le monde extérieur (vous pouvez trouver les raisons pour lesquelles vous voudriez le faire ici )Supposons maintenant que vous ayez introduit ce champ sur un tas de modèles existants et que vous vouliez maintenant régénérer tous les enregistrements qui ne sont pas encore définis. Vous pouvez faire ça comme ça
vous pouvez maintenant courir
rake di:public_uids:generate
la source