2010-01-12 196 views
9

我想知道我可以在Rails中使用关联的程度。考虑到以下情况:rails has_many:通过has_many:通过

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.businessesProvider.bids但如何做这样的事情User.bids?可以联想一个联想吗?可以这么说吗?

回答

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 

但是从出价得到一个用户将采取更多的工作,获取属于用户所有投标。

+2

这是可能的,但需要小心你的嵌套深度,因为你可能会陷入你的数据库和Rails应用程序。话虽如此,我写了一篇博客文章,详细介绍了如何使用nested_has_many_through完成此操作:http://kconrails.com/2010/01/28/nesting-has_many-through-relationships-in-ruby-on-rails/ – 2010-10-23 03:11:19

2

虽然这是一个非常有用的东西,你不能has_many:通过has_many:through关系。这是连接引擎的限制。

替代方法是使用巧妙的子选择,或者在这种情况下使用子子选择,或者故意使表格非规格化以减少连接深度。

例如,由于业务是在提供商的上下文内定义的,因此任何投标元素也间接分配给提供商是理所当然的。建立投标和提供商之间的直接联系可以使查询出价变得很容易。

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应该产生期望的结果,你也可以缓存出价,如果你想要做其他花哨的东西。

+0

'bids'如何被缓存,因为它是非静态数据?我们如何知道更新缓存? – 2012-10-18 17:03:27

4

如果你只是想取记录,为什么不使用使用#delegate?它工作得很好,至少在你描述的场景中。

class User < ActiveRecord::Base 
    has_one :provider 
    delegates :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 

虽然我不那么谦虚,认为你应该只是链的方法,因为它更简单,而且你不再除非你有一些疯狂的自定义SQL去,因为tadman说,实现性能提升。