2011-11-29 41 views
8

我在使用Rails(3.1.3)加载应用程序初始化中的一些ActiveRecord子类时遇到问题。这里是目录结构,我有:在Rails初始化中加载子语句

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

我试图利用Class1.subclasses,但它一直返回[]。将#{config.root}/app/models/class1s添加到config.autoload_paths并没有帮助,因为这些类是惰性加载的,并且在我调用subclasses之前没有引用子类,因此它们尚未加载。将路径添加到config.eager_load_paths似乎也不起作用,其行为基于config.cache_classes设置,该设置在开发和生产中通常是不同的。

我希望能够启动轨道控制台看到:

> Class1.subclasses 
=> [Subclass1, Subclass2] 

现在这是我看到的行为:

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

现在我减少到推杆这在我的Class1定义的底部,把所有的子类的就当我访问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 

它完成了工作,但我觉得这样做很脏。任何想法将不胜感激。

回答

2

做到这一点最简单的方法,是使用只加载的所有类(> = 3.0):

Rails.application.eager_load! 

它会加载从您的应用程序,引擎,插件的所有类。与在配置中延迟加载的转向结果相同。但是在这种方法中,你不需要使用这种方法。

2

急切加载的问题是,一旦一个类发生变化,那么子类将不再被加载。我在我的development.rb中使用了一个constantizer,它在每个请求上通过文件名使我的所有子类(即子目录)一致。我把它放在lib中,因为有些测试需要对事物进行排序。

的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 

应用程序/环境/ 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

预先加载在开发环境中默认为禁用。

config/environments/development.rb

config.eager_load = true 
启用它