¿Hay alguna manera de que puedas obtener una colección de todos los Modelos en tu aplicación Rails?
Básicamente, ¿puedo hacer los gustos de: -
Models.each do |model|
puts model.class.name
end
¿Hay alguna manera de que puedas obtener una colección de todos los Modelos en tu aplicación Rails?
Básicamente, ¿puedo hacer los gustos de: -
Models.each do |model|
puts model.class.name
end
Respuestas:
EDITAR: mira los comentarios y otras respuestas. ¡Hay respuestas más inteligentes que esta! O intente mejorar este como wiki comunitario.
Los modelos no se registran en un objeto maestro, por lo que no, Rails no tiene la lista de modelos.
Pero aún puede buscar en el contenido del directorio de modelos de su aplicación ...
EDITAR: Otra idea (salvaje) sería usar la reflexión Ruby para buscar todas las clases que extiendan ActiveRecord :: Base. Sin embargo, no sé cómo puedes enumerar todas las clases ...
EDITAR: solo por diversión, encontré una manera de enumerar todas las clases
EDITAR: Finalmente logró enumerar todos los modelos sin mirar directorios
Si también desea manejar la clase derivada, deberá probar toda la cadena de superclase. Lo hice agregando un método a la clase Class:
fuente
RAILS_ROOT
ya no está disponible en Rails 3. En su lugar, useDir.glob(Rails.root.join('app/models/*'))
ActiveRecord::Base
ahora, por lo que si desea cargar todos los modelos, puede iterarlos fácilmente; vea mi respuesta a continuación.La respuesta completa para los rieles 3, 4 y 5 es:
Si
cache_classes
está desactivado (por defecto está desactivado en desarrollo, pero activado en producción):Luego:
Esto asegura que todos los modelos en su aplicación, independientemente de dónde se encuentren, se carguen y las gemas que está utilizando que proporcionan modelos también se cargan.
Esto también debería funcionar en clases que heredan
ActiveRecord::Base
, comoApplicationRecord
en Rails 5, y devuelven solo ese subárbol de descendientes:Si desea saber más sobre cómo se hace esto, consulte ActiveSupport :: DescendantsTracker .
fuente
:environment
paraeager_load!
que funcione.Rails.application.eager_load!
, simplemente puede cargar los modelos:Dir.glob(Rails.root.join('app/models/*')).each do |x| require x end
Rails.paths["app/models"].existent
directorios. La ansiosa carga de toda la aplicación es una respuesta más completa y se asegurará de que no quede absolutamente ningún lugar para definir los modelos.Rails.application.paths["app/models"].eager_load!
En caso de que alguien tropiece con este, tengo otra solución, no confiar en la lectura de directorios o extender la clase Class ...
Esto devolverá una variedad de clases. Entonces puedes hacer
fuente
ActiveRecord::Base.subclasses
pero tienes que usarsend
? Además, parece que tiene que "tocar" el modelo antes de que aparezca, por ejemplo,c = Category.new
y aparecerá. De lo contrario, no lo hará.ActiveRecord::Base.descendants
ActiveRecord::Base.descendants
enumerarlos.volverá
Información adicional Si desea llamar a un método en el nombre del objeto sin modelo: método desconocido de cadena o errores variables, use esto
fuente
ActiveRecord::Base.send :subclasses
: buscar los nombres de las tablas es una buena idea. Generar automáticamente los nombres de los modelos puede ser problemático como se menciona anteriormente..capitalize.singularize.camelize
puede ser reemplazado a.classify
.Busqué formas de hacer esto y terminé eligiendo de esta manera:
fuente: http://portfo.li/rails/348561-how-can-one-list-all-database-tables-from-one-project
fuente
ActiveRecord::Base.connection.tables.each{|t| begin puts "%s: %d" % [t.humanize, t.classify.constantize.count] rescue nil end}
algunos de los modelos pueden no estar activados, por lo tanto, debe rescatarlo.model_classes = ActiveRecord::Base.connection.tables.collect{|t| t.classify.constantize rescue nil }.compact
Para Rails5, los modelos ahora son subclases de
ApplicationRecord
modo que para obtener una lista de todos los modelos en su aplicación, haga lo siguiente:O más corto:
Si está en modo de desarrollo, necesitará cargar modelos antes de:
fuente
Creo que la solución de @ hnovick es genial si no tienes modelos sin mesa. Esta solución también funcionaría en modo de desarrollo
Sin embargo, mi enfoque es sutilmente diferente:
Se supone que classify te da el nombre de la clase de una cadena correctamente . safe_constantize asegura que puede convertirlo en una clase de forma segura sin lanzar una excepción. Esto es necesario en caso de que tenga tablas de base de datos que no sean modelos. compacto para que se eliminen los nulos en la enumeración.
fuente
safe_constantize
.Si solo quieres los nombres de clase:
Simplemente ejecútalo en la consola de Rails, nada más. ¡Buena suerte!
EDITAR: @ sj26 es correcto, primero debe ejecutar esto antes de poder llamar a los descendientes:
fuente
map
conputs
? No entiendo el punto debería serActiveRecord::Base.descendants.map(&:model_name)
Esto parece funcionar para mí:
Rails solo carga modelos cuando se usan, por lo que la línea Dir.glob "requiere" todos los archivos en el directorio de modelos.
Una vez que tenga los modelos en una matriz, puede hacer lo que estaba pensando (por ejemplo, en el código de vista):
fuente
...'/app/models/**/*.rb'
En una línea:
Dir['app/models/\*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
fuente
Dir['**/models/**/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize }
ActiveRecord::Base.connection.tables
fuente
En solo una línea:
fuente
Rails.application.eager_load!
antes de la ejecución en modo de desarrollo.Todavía no puedo comentar, pero creo que la respuesta sj26 debería ser la respuesta principal. Solo una pista:
fuente
Con Rails 6 , Zetiwerk convirtió en el cargador de código predeterminado.
Para una carga ansiosa, intente:
Luego
fuente
Sí, hay muchas formas de encontrar todos los nombres de modelos, pero lo que hice en mi gema model_info es que te dará todos los modelos incluso incluidos en las gemas.
entonces simplemente imprima esto
fuente
Esto funciona para Rails 3.2.18
fuente
Para evitar la carga previa de todos los rieles, puede hacer esto:
require_dependency (f) es lo mismo que
Rails.application.eager_load!
usa. Esto debería evitar errores de archivo ya requeridos.Luego puede usar todo tipo de soluciones para enumerar modelos AR, como
ActiveRecord::Base.descendants
fuente
fuente
Aquí hay una solución que ha sido examinada con una aplicación Rails compleja (la que impulsa Square)
Toma las mejores partes de las respuestas en este hilo y las combina en la solución más simple y completa. Este maneja casos donde sus modelos están en subdirectorios, use set_table_name, etc.
fuente
Acabo de encontrar este, ya que necesito imprimir todos los modelos con sus atributos (basados en el comentario de @Aditya Sanghi):
fuente
Esto funcionó para mí. Un agradecimiento especial a todas las publicaciones anteriores. Esto debería devolver una colección de todos sus modelos.
fuente
Los
Rails
implementa el métododescendants
, pero los modelos no necesariamente siempre hereda deActiveRecord::Base
, por ejemplo, la clase que incluye el móduloActiveModel::Model
tendrá el mismo comportamiento que un modelo, simplemente no estarán vinculados a una mesa.Entonces, complementando lo que dicen los colegas anteriores, el más mínimo esfuerzo haría esto:
Monkey Patch de la clase
Class
de Ruby:y el método
models
, incluidos los ancestros, como este:El método
Module.constants
devuelve (superficialmente) una colección desymbols
, en lugar de constantes, por lo que el métodoArray#select
puede sustituirse como este parche de mono deModule
:Parche de mono de
String
.Y, finalmente, el método de los modelos.
fuente
Esto te dará todas las clases de modelos que tienes en tu proyecto.
fuente
fuente
He intentado muchas de estas respuestas sin éxito en Rails 4 (wow, cambiaron una o dos cosas por el amor de Dios) decidí agregar la mía. Los que llamaron a ActiveRecord :: Base.connection y obtuvieron los nombres de las tablas funcionaron pero no obtuvieron el resultado que quería porque escondí algunos modelos (en una carpeta dentro de app / models /) que no quería Eliminar:
Lo puse en un inicializador y puedo llamarlo desde cualquier lugar. Previene el uso innecesario del mouse.
fuente
puede verificar esto
fuente
Suponiendo que todos los modelos están en la aplicación / modelos y que tiene grep & awk en su servidor (la mayoría de los casos),
Es más rápido
Rails.application.eager_load!
o recorre cada archivo conDir
.EDITAR:
La desventaja de este método es que pierde modelos que heredan indirectamente de ActiveRecord (por ejemplo
FictionalBook < Book
). La forma más segura esRails.application.eager_load!; ActiveRecord::Base.descendants.map(&:name)
, aunque sea un poco lenta.fuente
Solo estoy lanzando este ejemplo aquí si alguien lo encuentra útil. La solución se basa en esta respuesta https://stackoverflow.com/a/10712838/473040 .
Digamos que tiene una columna
public_uid
que se utiliza como ID principal para el mundo exterior (puede encontrar las razones por las que desea hacer eso aquí )Ahora supongamos que ha introducido este campo en un montón de modelos existentes y ahora desea regenerar todos los registros que aún no se han establecido. Puedes hacer eso así
ahora puedes correr
rake di:public_uids:generate
fuente