在Rails 3.1中的seeds.rb中包含Railtie初始化

时间:2011-11-23 19:42:06

标签: ruby-on-rails ruby-on-rails-3

我创建了一个简单的铁路,向ActiveRecord添加了一堆东西:

  0 module Searchable
  1   class Railtie < Rails::Railtie
  2     initializer 'searchable.model_additions' do
  3       ActiveSupport.on_load :active_record do
  4         extend ModelAdditions
  5       end
  6     end
  7   end
  8 end

我需要这个文件(在/ lib中),在调用应用程序之前将以下行添加到config / environment.rb:

require 'searchable'

这适用于我的应用程序,并且没有重大问题。

但是我遇到了rake db:seed的问题。

在我的seeds.rb文件中,我从csv中读取数据并填充数据库。我遇到的问题是我对ActiveRecord的添加没有加载,种子因method_missing错误而失败。我没有调用这些方法,但我认为,由于seeds.rb加载模型,它会尝试调用某些方法,这就是它失败的原因。

任何人都可以告诉我一个更好的地方放置要求,以便每次加载ActiveRecord时都会包含它(不仅仅是在加载完整的应用程序时)?我希望将代码保留在我的模型之外,因为它是我的大多数模型之间共享的代码,我想保持它们干净和干燥。

1 个答案:

答案 0 :(得分:0)

将扩展名添加到ActiveRecord :: Base。

当引用模型类时,通过Rails 3.1自动加载/常量查找,它将加载该类。在那一点上,基本上是纯粹的Ruby(没有什么魔力)。所以我认为你至少有几个选择。 “坏”选项,你想要它挂钩到依赖加载。也许是这样的:

module ActiveSupport
  module Dependencies
    alias_method(:load_missing_constant_renamed_my_app_name_here, :load_missing_constant)
    undef_method(:load_missing_constant)
    def load_missing_constant(from_mod, const_name)
       # your include here if const_name = 'ModelName'
       # perhaps you could list the app/models directory, put that in an Array, and do some_array.include?(const_name)
       load_missing_constant_renamed_my_app_name_here(from_mod, const_name)
    end
  end
end

另一种方法是使用像你一样的Railtie并向ActiveRecord :: Base添加一个类方法,然后包含东西,如:

module MyModule
  class Railtie < Rails::Railtie
    initializer "my_name.active_record" do
      ActiveSupport.on_load(:active_record) do
        # ActiveRecord::Base gets new behavior
        include ::MyModule::Something # where you add behavior. consider using an ActiveSupport::Concern
      end
    end
  end
end

如果使用ActiveSupport :: Concern:

module MyModule
  module Something
    extend ActiveSupport::Concern

    included do
      # this area is basically for anything other than class and instance methods
      # add class_attribute's, etc.
    end

    module ClassMethods
      # class method definitions go here

      def include_some_goodness_in_the_model
        # include or extend a module
      end 
    end

    # instance method definitions go here
  end
end

然后在每个模型中:

class MyModel < ActiveRecord::Base

  include_some_goodness_in_the_model

  #...

end

然而,这并不比仅仅在每个模型中进行包含更好,这是我推荐的。