我想知道我可以在多大程度上使用Rails中的关联。考虑以下因素:
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
我可以设置User.businesses
和Provider.bids
这些漂亮的快捷方式,但是如User.bids
这样做呢?是否可以关联一个关联,可以这么说?
答案 0 :(得分:5)
这是完全可能的,但需要一些额外的工作。以下与nested_has_many plugin结合使用的模型定义,您只需@user.bids
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
has_many :bids, :through => :businesses
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
但是,从出价中获取用户需要做更多工作。
答案 1 :(得分:4)
如果您只想获取记录,为什么不使用#delegate
?它工作正常,至少在您描述的场景中。
class User < ActiveRecord::Base
has_one :provider
delegate :bids, :to => :provider
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
虽然在我不那么谦虚的意见中你应该把这些方法链接起来,因为它更直接,而且除非你像Tadman所说的那样使用一些疯狂的自定义SQL,否则你不再能够提升性能。
答案 2 :(得分:1)
虽然这是一个非常有用的东西,但你不能通过has_many:through关系来实现。这是联接引擎的限制。
替代方法要么使用聪明的子选择,要么使用子子选择,或者有意地对表进行非规范化以减少连接深度。
例如,由于业务是在提供商的上下文中定义的,因此任何Bid元素也会间接地分配给提供商。在Bid和Provider之间建立直接关联可以直接轻松查询出价。
答案 3 :(得分:0)
没有什么能阻止你做这样的事情:
class User < ActiveRecord::Base
has_one :provider
has_many :businesses, :through => :provider
def bids
user_bids = []
businesses.each |business| do
user_bids += business.bids
end
user_bids
end
end
class Provider < ActiveRecord::Base
has_many :businesses
has_many :bids, :through => :businesses
belongs_to :user
end
class Business < ActiveRecord::Base
has_many :bids
belongs_to :provider
end
class Bid < ActiveRecord::Base
belongs_to :business
end
然后调用@ user.bids应该会产生所需的结果,如果需要,您也可以缓存出价并做其他奇特的事情。