2011-05-04 9 views
8

Quiero mostrar una lista de selección de subclases de MyModel en una vista. No está funcionando todavía, así que para el control de la cordura, incluí esto en mi punto de vista:RoR: MyModel.descendants devuelve [] en una vista después de la primera llamada?

<%= MyModel.descendants %> 

El primera tiempo me hacen esta página después de reiniciar el servidor, se muestra la lista de los descendientes (hay seis) Todos posteriores veces, aparece como una lista vacía [].

Fwiw, que tiene declaración require en mis inicializadores:

Dir[Rails.root.join("app/models/my_models/**/*.rb").to_s].each {|f| require f} 

... y he verificado que están siendo requeridos.

Lo que el @ ($% & está pasando?

Respuesta

7

Cuando se utiliza necesita, incluso si su my_model.rb consigue Reloaded, el núcleo no requerirá sus subclases .rb archivos debido a que ya se han cargado. Usted' d tienen que pasar por los carriles de carga automática.

Básicamente, en su primera solicitud, los carriles autoloads MyModel de my_model.rb, que a su vez requiere my_models/sub_model.rb. la clase hereda SubModelMyModel, que llena la matriz descendants. en usted Sin embargo, después de las siguientes solicitudes, Rails autocarga MyModel nuevamente (hey, estás en modo dev), que luego requiere my_models/sub_model.rb nuevamente. Pero esta vez, el kernel sabe que ya ha cargado este archivo y no lo cargará nuevamente.

Me encontré con este problema hace una hora, lo que me llevó a su publicación, y para encontrar una solución. Lo que necesitamos son raíles para auto cargar subclases cada vez que se llame a su clase principal.

Aquí es una solución:

class MyModel 
    Dir[File.join(File.dirname(__FILE__),"my_models","*.rb")].each do |f| 
    MyModels.const_get(File.basename(f,'.rb').classify) 
    end 
end 

Estas líneas probablemente podría ser puesto fuera de la clase. Eso debería ser suficiente (es para mí) si solo tiene archivos en my_models y no en subdirectorios. Si tiene alguna (por ejemplo MyModels::Car::Ford, puede que tenga que poner el mismo tipo de cosas en los submódulos (en my_models/car.rb)

+0

+1 para la explicación lúcida de lo que está sucediendo, gracias. Desafortunadamente, mis subclases tienen nombres de "acrónimos", como "PGEService" con nombres de archivo como "pge_service.rb". No estoy listo para cambiar el nombre de mis archivos a 'p_g_e_service.rb', ¡al menos no todavía! –

+0

Bueno, si sus archivos se llaman PGEService.rb, puede simplemente usar el nombre del archivo (sin el '.clasifique'), pero no veo ninguna solución fácil si todavía es 'pge_service.rb' ... A menos que, por supuesto, haga algo como' s = File.basename (f, '. rb'). split ('_ '); class_name = s.first.upcase + s.last.classify; MyModels.const_get (class_name) '. Sí, un poco feo, lo sé. – Wam

+0

hablando estrictamente, HIZO responder mi pregunta de "qué está pasando". Entonces te mereces la marca de verificación. He refinado mi pregunta, pero la publicaré como una pregunta separada. ¡Adelante! –

9

que tenían el mismo problema solucionado mediante la adición de un config/initializers/preload_models.rb con:..

Dir[Rails.root + 'app/models/*.rb'].map {|f| File.basename(f, '.*').camelize.constantize } 
.

la esperanza de que ayude a alguien

+0

Esto me ayudó ... ¡Gracias! – erroric

+0

Esto no funcionará si está utilizando el espacio de nombres desafortunadamente :( – mscriven

+0

Esto también sigue sin memoria después de unos minutos, cuando acaba de cargarse a través del inicializador. – Todd

7

acabo de activar la carga ansiosa en cada entorno:

config.eager_load = true

Esto funcionó para mí incluso cuando usa espacios de nombres para nombres de clase.

+0

Creo que * esta será la respuesta ganadora. ¿Alguien más puede verificar que esto funcione? –

+0

Esto funcionó para mí – Philip7899

+0

Esto es un falso positivo, funcionará para unos minutos, luego se le agota la memoria. Cualquiera que sea la página con la que esté usando esta función, simplemente actualice lo suficiente y, finalmente, los 'descendientes' o' las subclases comenzarán a volver a estar en blanco de nuevo. – Todd

Cuestiones relacionadas