【问题标题】:Include Railtie initialization in seeds.rb in Rails 3.1在 Rails 3.1 的 seed.rb 中包含 Railtie 初始化
【发布时间】:2012-09-22 21:26:54
【问题描述】:

我创建了一个简单的 railtie,向 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 的问题。

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

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

【问题讨论】:

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


    【解决方案1】:

    将扩展放在那里只是将它添加到 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
    

    但是,这并不比只在每个模型中包含一个好多少,这是我推荐的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      • 2023-01-13
      • 2015-06-02
      • 2021-07-05
      • 2011-08-16
      相关资源
      最近更新 更多