我已经成为一个复杂的模型,我正试图干掉它。对于我的has_many选项,我不想让它们重复,而是简单地从类中的方法加载它们。
class ExampleClass < ActiveRecord::Base
has_many :related_things, get_association_hash(arg1)
has_many :other_things, get_association_hash(arg2)
def get_association_hash(arg)
{ :class_name => 'SomeClass', :conditions => ['table.column = ?', arg] }
end
end
不幸的是,加载课程时会产生undefined method ‘get_association_hash’ for #<Class:0x007f9ae9efe6c0>
。
(作为一个完整性检查,如果我只是单独调用它,而不将其包含在has_many中,那么该方法就可以了。而且,实际的类相当大,所以DRY比这个小例子更有用。)< / p>
我注意到错误消息提到Class
,而不是我的派生ExampleClass
,所以也许它与has_many的加载方式有关,以及我定义方法的位置?
答案 0 :(得分:1)
has_many
只是一个类方法所以:
has_many :related_things, get_association_hash(arg1)
只是一个方法调用,而且该上下文中的接收者是你的ExampleClass
。这意味着get_association_hash
需要是一个类方法。您还必须在 has_many
来电之前定义,否则您将无法在任何地方拨打电话:
class ExampleClass < ActiveRecord::Base
def self.get_association_hash(arg)
{ :class_name => 'SomeClass', :conditions => ['table.column = ?', arg] }
end
has_many :related_things, get_association_hash(arg1)
has_many :other_things, get_association_hash(arg2)
end
这可能有点难看,并且弄乱了通常的定义顺序。如果是这种情况,那么您可以将get_association_hash
方法推送到模块中,然后将该模块包含在班级的顶部:
module Pancakes
def self.included(base)
# There are various different ways to do this, use whichever one you like best
base.class_exec do
def self.get_association_hash(arg)
# ...
end
end
end
end
class ExampleClass < ActiveRecord::Base
include Pancakes
has_many :related_things, get_association_hash(arg1)
has_many :other_things, get_association_hash(arg2)
end
你可能会把你的模块称为比Pancakes
更合理的东西,这只是我的默认名称(因为 foo 在一段时间后变得无聊而我更喜欢Fargo传统)。