我有一些像这样的模型(Rails 3.2),A->B->C,用来为一个覆盖许多区域(B)的Manager(A)建模,每个区域都有许多地址(C)。其中一个地址是经理的主要地址。我想不出将经理与他的主要地址联系起来的最佳方式。
class AreaManager < ActiveRecord::Base
has_many :areas, :dependent=>:destroy
has_many :addresses, :through=>:areas
...
def primary_address
self.addresses.where(:primary=>true).first
# in fact, there can be only one
end
end
class Area < ActiveRecord::Base
belongs_to :area_manager
has_many :addresses,:dependent=>:destroy
end
class Address < ActiveRecord::Base
belongs_to :area
attr_accessible :primary
# this is the manager's primary address (not the area's)
end
这让我可以说,例如:
a = AreaManager.find(123)
a.primary_address # => her primary address
但我真正想要的是一个构造函数/设置器以及一个getter:
a = AreaManager.new
a.build_primary_address ...
我可以添加到区域:
has_one :primary_address,
:class_name=>'Address',
:conditions => {:primary=>true}
这让我可以做
a1 = Area.new
a1.build_primary_address ... # instantiates an Address with primary = true
但当我尝试做一些类似于AreaManager的事情时,通过添加
has_one :primary_address,
:through=>:areas,
:source=>:address,
:conditions=>{:primary=>true}
然后说:
a = AreaManager.new
a.build_primary_address ...
# instead of creating an area and an address, it croaks
我得到一个ActiveRecord::HasOneThroughCantAssociateThroughCollection异常。我不知道什么是正确的咒语(或者是否有)。有Railsy的方法吗?
由于rails都是关于以下约定和许多选项中的正确chocie,我建议:
-
不将条件应用于关联
-
查找以使用命名的
scope
-
请使用
.where
(rails3)而不是conditions
(rails2)。有关更多信息,请参阅ActiveRecord api应用所有这些可能会稍微改变你的代码,你会得到不同的结果。