我创建了一个简单的铁路,向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时都会包含它(不仅仅是在加载完整的应用程序时)?我希望将代码保留在我的模型之外,因为它是我的大多数模型之间共享的代码,我想保持它们干净和干燥。
答案 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
然而,这并不比仅仅在每个模型中进行包含更好,这是我推荐的。