2010-01-12 19 views
9

Zastanawiam się, w jakim stopniu mogę używać asocjacji w Railsach. Wziąć pod uwagę następujące elementy:szyny has_many: through has_many: through

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 

jestem w stanie skonfigurować te ładne skróty jak User.businesses i Provider.bids ale co robić coś podobnego User.bids? Czy można tak powiedzieć stowarzyszenia?

Odpowiedz

5

Jest to całkowicie możliwe, ale wymaga trochę dodatkowej pracy. Poniższe definicje modelu wykorzystane w połączeniu z nested_has_many plugin można pobrać wszystkie oferty należące do użytkownika z zaledwie @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 

Jednak coraz użytkownika z oferty zajmie więcej pracy.

+2

Jest to możliwe, ale trzeba uważać na to, jak głęboko zagnieżdżasz się, ponieważ możesz uszkodzić aplikację bazy danych i szyn. Biorąc to pod uwagę, napisałem post na blogu, który opisuje, w jaki sposób użyć nested_has_many_through, aby to zrobić: http://kconrails.com/2010/01/28/nesting-has_many-through-relationships-in-ruby-on-rails/ –

2

Chociaż jest to bardzo przydatna rzecz, nie można mieć wiele: poprzez związek has_many: through. To jest ograniczenie mechanizmu łączenia.

Alternatywą jest albo użycie sprytnego pod-wyboru, albo w tym przypadku pod-podrzędnego wyboru, albo celowe denormalizacja tabel w celu zmniejszenia głębokości łączenia.

Na przykład, ponieważ Biznes jest zdefiniowany w kontekście Dostawcy, oczywiste jest, że wszelkie elementy Oferty są również pośrednio przypisane Dostawcy. Utworzenie bezpośredniego powiązania między ofertą a dostawcą sprawi, że stawki za zapytania będą bezpośrednio łatwe.

0

Nic nie zatrzymując robisz coś w tym AFAIK:

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 

następnie wywołanie @ user.bids powinna wywołać pożądany efekt, można także buforować ofert i wykonywać inne wymyślnych rzeczy, jeśli chcesz.

+0

W jaki sposób "oferty" będą buforowane, ponieważ są to dane niestatyczne? Skąd wiemy, aby zaktualizować pamięć podręczną? –

4

Jeśli chcesz tylko pobrać rekordy, dlaczego nie użyć funkcji #delegate? Działa dobrze, przynajmniej w scenariuszu, który opisałeś.

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 

Chociaż w moim nie tak skromnym-zdaniem należy po prostu łańcuch metody, ponieważ jest to bardziej oczywiste, a ty nie jesteś już osiągnięcie wzrost wydajności, chyba że idziesz z jakimś szalonym niestandardowego SQL jak mówi tadman.

Powiązane problemy