2011-11-29 15 views
8

Tengo problemas para hacer que Rails (3.1.3) cargue algunas de mis subclases ActiveRecord en la inicialización de la aplicación. Esta es la estructura de directorios que tengo:Cargar Subclases en Rails Inicialización

- models 
    - class1.rb # Class1 < ActiveRecord::Base 
    - class1s 
    - subclass1.rb # Subclass1 < Class1 
    - subclass2.rb # Subclass2 < Class1 

que estoy tratando de hacer uso de Class1.subclasses, pero sigue regresando []. Agregar #{config.root}/app/models/class1s a config.autoload_paths no ayuda porque esas clases tienen una carga lenta y nada hace referencia a las subclases antes de hacer una llamada al subclasses, por lo que todavía están cargados. Agregar la ruta a config.eager_load_paths tampoco parece funcionar, y su comportamiento se basa en la configuración config.cache_classes que generalmente es diferente en desarrollo y producción.

Me gustaría ser capaz de poner en marcha la consola carriles y ver:

> Class1.subclasses 
=> [Subclass1, Subclass2] 

En este momento este es el comportamiento que veo:

> Class1.subclasses 
=> [] 
> Subclass1 
=> Subclass1 
> Class1.subclasses 
=> [Subclass1] 
> Subclass2 
=> Subclass2 
> Class1.subclasses 
=> [Subclass1, Subclass2] 

En este momento estoy reducido a poner esta en el fondo de mi definición clase 1 para obtener todas las subclases para cargar en cuando accedo a la clase Class1:

ruby_files_pattern = File.join(Rails.application.config.root, "app", "models", "class1s", "**", "*.rb") 
Dir.glob(ruby_files_pattern).each do |file| 
    ActiveSupport::Dependencies.require_or_load(file) 
end 

Hace el trabajo, pero me siento sucio haciéndolo. Cualquier pensamiento sería muy apreciado.

Respuesta

2

La forma más sencilla de hacer eso, se acaba de cargar todas las clases usando (> = 3.0):

Rails.application.eager_load! 

se carga todas las clases de la aplicación, los motores, plugins. Es el mismo resultado que el cambio de carga lenta en config. Pero en este enfoque, no necesita hacer eso solo use este método.

2

El problema con la carga ansiosa es que una vez que una clase cambia, las subclases ya no se cargarán. Yo uso un constantizer en mi development.rb que constata todas mis subclases (e.i. subdirectorios) por nombre de archivo en cada solicitud. Lo puse en libertad ya que algunas pruebas también necesitan contaminar cosas.

lib/constantizer.rb

class Constantizer 
    def self.path(path, include_current_path=true, namespace_prefix='') 
    dirs = Dir[Rails.root.join(path, '**', '**')].select { |f| File.directory?(f) && File.basename(f) != 'concerns'} 
    dirs << Rails.root.join(path) if include_current_path 
    dirs.each do |dir| 
     Dir["#{dir}/*.rb"].each do |file| 
     (namespace_prefix + file.chomp(".rb").split("/").last.camelize).constantize 
     end 
    end 
    end 
end 

aplicación/medio ambiente/development.rb

class ConstantizeAllSubclasses 
    def initialize(app) 
    @app = app 
    end 

    def call(env) 
    Constantizer.path('app/models', false) 
    @app.call(env) 
    end 
end 

Project::Application.configure do 
    # Usual config items 
    config.middleware.insert_after Warden::Manager, ConstantizeAllSubclasses 
end 
0

Eager Cargando está desactivado en el entorno de desarrollo de manera predeterminada.

active desde config/environments/development.rb

config.eager_load = true