2010-01-12 244 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說,實現性能提升。