Gibt es eine Möglichkeit, eine Sammlung aller Modelle in Ihrer Rails-App abzurufen?
Grundsätzlich kann ich Folgendes tun: -
Models.each do |model|
puts model.class.name
end
Gibt es eine Möglichkeit, eine Sammlung aller Modelle in Ihrer Rails-App abzurufen?
Grundsätzlich kann ich Folgendes tun: -
Models.each do |model|
puts model.class.name
end
Antworten:
EDIT: Schauen Sie sich die Kommentare und andere Antworten an. Es gibt klügere Antworten als diese! Oder versuchen Sie, dieses als Community-Wiki zu verbessern.
Modelle registrieren sich nicht bei einem Master-Objekt. Nein, Rails verfügt nicht über die Liste der Modelle.
Sie können aber trotzdem im Inhalt des Modellverzeichnisses Ihrer Anwendung nachsehen ...
BEARBEITEN: Eine andere (wilde) Idee wäre, Ruby Reflection zu verwenden, um nach allen Klassen zu suchen, die ActiveRecord :: Base erweitern. Ich weiß nicht, wie Sie alle Klassen auflisten können ...
EDIT: Nur zum Spaß habe ich einen Weg gefunden, alle Klassen aufzulisten
BEARBEITEN: Endlich gelang es, alle Modelle aufzulisten, ohne die Verzeichnisse zu betrachten
Wenn Sie auch abgeleitete Klassen verarbeiten möchten, müssen Sie die gesamte Oberklassenkette testen. Ich habe dazu der Class-Klasse eine Methode hinzugefügt:
quelle
RAILS_ROOT
ist nicht mehr in Rails 3 verfügbar. VerwendenDir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
jetzt. Wenn Sie also alle Modelle laden möchten, können Sie sie leicht iterieren - siehe meine Antwort unten.Die ganze Antwort für die Schienen 3, 4 und 5 lautet:
Wenn deaktiviert
cache_classes
ist (standardmäßig ist es in der Entwicklung deaktiviert, in der Produktion jedoch aktiviert):Dann:
Auf diese Weise wird sichergestellt, dass alle Modelle in Ihrer Anwendung geladen werden, unabhängig davon, wo sie sich befinden, und dass alle von Ihnen verwendeten Edelsteine, die Modelle bereitstellen, ebenfalls geladen werden.
Dies sollte auch für Klassen funktionieren
ActiveRecord::Base
, die wieApplicationRecord
in Rails 5 erben und nur den Teilbaum der Nachkommen zurückgeben:Wenn Sie möchten mehr darüber wissen , wie dies geschehen ist, überprüfen Active :: DescendantsTracker .
quelle
:environment
für dieeager_load!
an der Arbeit.Rails.application.eager_load!
, können Sie einfach die Modelle laden:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
Verzeichnisse glob . Das eifrige Laden der gesamten Anwendung ist eine vollständigere Antwort und stellt sicher, dass für die Definition von Modellen absolut nichts mehr übrig ist.Rails.application.paths["app/models"].eager_load!
Nur für den Fall, dass jemand über diese stolpert, habe ich eine andere Lösung, ohne mich auf das direkte Lesen oder Erweitern der Klassenklasse zu verlassen ...
Dies gibt ein Array von Klassen zurück. So können Sie dann tun
quelle
ActiveRecord::Base.subclasses
aber benutzensend
? Es scheint auch so, als müssten Sie das Modell "berühren", bevor es beispielsweisec = Category.new
angezeigt wird und angezeigt wird. Sonst wird es nicht.ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
sie aufgelistet werden.wird zurückkehren
Zusätzliche Informationen Wenn Sie eine Methode für den Objektnamen ohne Modell aufrufen möchten: Zeichenfolge unbekannte Methode oder Variablenfehler verwenden Sie diese
quelle
ActiveRecord::Base.send :subclasses
- das Suchen nach Tabellennamen ist eine gute Idee. Das automatische Generieren der Modellnamen kann problematisch sein, wie bereits erwähnt..capitalize.singularize.camelize
kann ersetzt werden.classify
.Ich suchte nach Möglichkeiten, dies zu tun, und entschied mich schließlich für diesen Weg:
Quelle: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
quelle
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
Einige Modelle sind möglicherweise nicht aktiviert, daher müssen Sie sie retten.model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
Für Rails5 sind Modelle jetzt Unterklassen von
ApplicationRecord
, um eine Liste aller Modelle in Ihrer App zu erhalten, die Sie ausführen :Oder kürzer:
Wenn Sie sich im Entwicklungsmodus befinden, müssen Sie Modelle unbedingt laden, bevor Sie:
quelle
Ich denke, die Lösung von @ hnovick ist cool, wenn Sie keine Modelle ohne Tisch haben. Diese Lösung würde auch im Entwicklungsmodus funktionieren
Mein Ansatz ist jedoch subtil anders -
classify soll Ihnen den Namen der Klasse aus einer Zeichenfolge richtig geben . safe_constantize stellt sicher, dass Sie es sicher in eine Klasse verwandeln können, ohne eine Ausnahme auszulösen. Dies ist erforderlich, wenn Sie Datenbanktabellen haben, die keine Modelle sind. kompakt, so dass alle Nullen in der Aufzählung entfernt werden.
quelle
safe_constantize
.Wenn Sie nur die Klassennamen möchten:
Führen Sie es einfach in der Rails-Konsole aus, sonst nichts. Viel Glück!
EDIT: @ sj26 ist richtig, Sie müssen dies zuerst ausführen, bevor Sie Nachkommen aufrufen können:
quelle
map
mitputs
? Ich verstehe nicht, was der Punkt sein sollteActiveRecord::Base.descendants.map(&:model_name)
Das scheint bei mir zu funktionieren:
Rails lädt Modelle nur, wenn sie verwendet werden. Daher "benötigt" die Dir.glob-Zeile alle Dateien im Modellverzeichnis.
Sobald Sie die Modelle in einem Array haben, können Sie das tun, was Sie gedacht haben (z. B. im Ansichtscode):
quelle
...'/app/models/**/*.rb'
In einer Zeile:
Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
quelle
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
quelle
In nur einer Zeile:
quelle
Rails.application.eager_load!
vor der Ausführung im Entwicklungsmodus benötigt.Ich kann noch keinen Kommentar abgeben , aber ich denke, die Antwort von sj26 sollte die beste Antwort sein. Nur ein Hinweis:
quelle
Mit Rails 6 wurde Zetiwerk zum Standard-Code-Loader.
Versuchen Sie zum eifrigen Laden:
Dann
quelle
Ja, es gibt viele Möglichkeiten, wie Sie alle Modellnamen finden können, aber was ich in meinem Gem model_info getan habe, ist, dass Sie alle Modelle erhalten, die sogar in den Gems enthalten sind.
dann einfach ausdrucken
quelle
Dies funktioniert für Rails 3.2.18
quelle
Um zu vermeiden, dass alle Rails vorgeladen werden, können Sie Folgendes tun:
require_dependency (f) ist das gleiche, das
Rails.application.eager_load!
verwendet wird. Dies sollte bereits erforderliche Dateifehler vermeiden.Dann können Sie alle Arten von Lösungen verwenden, um AR-Modelle aufzulisten, wie z
ActiveRecord::Base.descendants
quelle
quelle
Hier ist eine Lösung, die mit einer komplexen Rails-App (der Powering Square) überprüft wurde.
Es nimmt die besten Teile der Antworten in diesem Thread und kombiniert sie in der einfachsten und gründlichsten Lösung. Dies behandelt Fälle, in denen sich Ihre Modelle in Unterverzeichnissen befinden, verwenden Sie set_table_name usw.
quelle
Ich bin gerade auf dieses Modell gestoßen, da ich alle Modelle mit ihren Attributen drucken muss (basierend auf dem Kommentar von @Aditya Sanghi):
quelle
Das hat bei mir funktioniert. Besonderer Dank geht an alle oben genannten Beiträge. Dies sollte eine Sammlung aller Ihrer Modelle zurückgeben.
quelle
Das
Rails
implementiert die Methodedescendants
, aber Modelle erben nicht unbedingt jemals vonActiveRecord::Base
beispielsweise der Klasse, die das Modul enthältActiveModel::Model
, haben das gleiche Verhalten wie ein Modell, werden jedoch nicht mit einer Tabelle verknüpft.Wenn man also die obigen Aussagen ergänzt, würde dies die geringste Anstrengung bewirken:
Affenfleck der Klasse
Class
des Rubins:und die Methode
models
, einschließlich der Vorfahren, wie folgt:Die Methode
Module.constants
gibt (oberflächlich) eine Sammlung vonsymbols
Konstanten anstelle von Konstanten zurück, sodass die MethodeArray#select
wie folgt ersetzt werden kannModule
:Affenbeet von
String
.Und schließlich die Modellmethode
quelle
Dadurch erhalten Sie alle Modellklassen, die Sie für Ihr Projekt haben.
quelle
quelle
Ich habe so viele dieser Antworten in Rails 4 erfolglos ausprobiert (wow, sie haben ein oder zwei Dinge geändert, um Himmels willen), dass ich beschlossen habe, meine eigenen hinzuzufügen. Diejenigen, die ActiveRecord :: Base.connection aufgerufen und die Tabellennamen abgerufen haben, haben funktioniert, aber nicht das gewünschte Ergebnis erzielt, da ich einige Modelle (in einem Ordner in app / models /) versteckt habe, die ich nicht wollte löschen:
Ich habe das in einen Initialisierer gesteckt und kann es von überall aufrufen. Verhindert unnötigen Mausgebrauch.
quelle
kann dies überprüfen
quelle
Angenommen, alle Modelle befinden sich in App / Modellen und Sie haben grep & awk auf Ihrem Server (in den meisten Fällen).
Es ist schneller als
Rails.application.eager_load!
oder durchläuft jede Datei mitDir
.BEARBEITEN:
Der Nachteil dieser Methode besteht darin, dass Modelle fehlen, die indirekt von ActiveRecord erben (z
FictionalBook < Book
. B. ). Der sicherste Weg istRails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, obwohl es ein bisschen langsam ist.quelle
Ich werfe dieses Beispiel nur hier, wenn jemand es nützlich findet. Die Lösung basiert auf dieser Antwort https://stackoverflow.com/a/10712838/473040 .
Angenommen, Sie haben eine Spalte
public_uid
, die als primäre ID für die Außenwelt verwendet wird (Gründe, warum Sie dies tun möchten, finden Sie hier ).Angenommen, Sie haben dieses Feld in einer Reihe vorhandener Modelle eingeführt und möchten nun alle noch nicht festgelegten Datensätze neu generieren. Sie können das so machen
Sie können jetzt laufen
rake di:public_uids:generate
quelle