¿Hay alguna manera de obtener una colección de todos los modelos en tu aplicación Rails?

Resuelto mr_urf asked hace 15 años • 29 respuestas

¿Existe alguna manera de obtener una colección de todos los modelos en su aplicación Rails?

Básicamente, ¿puedo hacer cosas como: -

Models.each do |model|
  puts model.class.name
end
mr_urf avatar Feb 05 '09 23:02 mr_urf
Aceptado

La respuesta completa para Rails 3, 4 y 5 es:

Si cache_classesestá desactivado (de forma predeterminada, está desactivado en desarrollo, pero activado en producción):

Rails.application.eager_load!

Entonces:

ActiveRecord::Base.descendants

Esto garantiza que todos los modelos de su aplicación, independientemente de dónde se encuentren, estén cargados y que también se carguen todas las gemas que esté utilizando y que proporcionen modelos.

Esto también debería funcionar en clases que heredan de ActiveRecord::Base, como ApplicationRecorden Rails 5, y devolver solo ese subárbol de descendientes:

ApplicationRecord.descendants

Si desea saber más sobre cómo se hace esto, consulte ActiveSupport::DescendantsTracker .

sj26 avatar May 23 '2012 02:05 sj26

En caso de que alguien se tope con esto, tengo otra solución, sin depender de la lectura de directorios ni de extender la clase Class...

ActiveRecord::Base.send :subclasses

Esto devolverá una serie de clases. Entonces puedes hacer

ActiveRecord::Base.send(:subclasses).map(&:name)
kikito avatar Jan 12 '2010 10:01 kikito

EDITAR: mire los comentarios y otras respuestas. ¡Hay respuestas más inteligentes que ésta! O intente mejorar este como wiki comunitario.

Los modelos no se registran en un objeto maestro, entonces no, Rails no tiene la lista de modelos.

Pero aún puedes buscar en el contenido del directorio de modelos de tu aplicación...

Dir.foreach("#{RAILS_ROOT}/app/models") do |model_path|
  # ...
end

EDITAR: Otra idea (loca) sería utilizar la reflexión de Ruby para buscar todas las clases que extiendan ActiveRecord::Base. Aunque no sé cómo puedes enumerar todas las clases...

EDITAR: Solo por diversión, encontré una manera de enumerar todas las clases.

Module.constants.select { |c| (eval c).is_a? Class }

EDITAR: Finalmente logré enumerar todos los modelos sin mirar directorios

Module.constants.select do |constant_name|
  constant = eval constant_name
  if not constant.nil? and constant.is_a? Class and constant.superclass == ActiveRecord::Base
    constant
  end
end

Si también desea manejar clases derivadas, deberá probar toda la cadena de superclases. Lo hice agregando un método a la clase Class:

class Class
  def extend?(klass)
    not superclass.nil? and ( superclass == klass or superclass.extend? klass )
  end
end

def models 
  Module.constants.select do |constant_name|
    constant = eval constant_name
    if not constant.nil? and constant.is_a? Class and constant.extend? ActiveRecord::Base
    constant
    end
  end
end
Vincent Robert avatar Feb 05 '2009 16:02 Vincent Robert
ActiveRecord::Base.connection.tables.map do |model|
  model.capitalize.singularize.camelize
end

regresará

["Article", "MenuItem", "Post", "ZebraStripePerson"]

Información adicional Si desea llamar a un método con el nombre del objeto sin modelo: método desconocido de cadena o errores de variable, use esto

model.classify.constantize.attribute_names
lightyrs avatar Dec 08 '2011 21:12 lightyrs