52

Szyny mają powiązanie has_one :through, które pomaga skonfigurować powiązanie jeden do jednego z trzecim modelem, przechodząc przez drugi model. Jakie jest rzeczywiste użycie tego, poza tworzeniem powiązania skrótów, które w przeciwnym razie byłoby o krok dalej.Szyny has_one: przez asocjację

Biorąc ten przykład z szyn guide:

class Supplier < ActiveRecord::Base 
    has_one :account 
    has_one :account_history, :through => :account 
end 

class Account < ActiveRecord::Base 
    belongs_to :supplier 
    has_one :account_history 
end 

class AccountHistory < ActiveRecord::Base 
    belongs_to :account 
end 

może pozwoli nam zrobić coś takiego:

supplier.account_history 

które w przeciwnym razie zostałyby osiągnięte jak:

supplier.account.history 

Jeśli jest to tylko dla łatwiejszego dostępu, to technicznie może istnieć powiązanie jeden do jednego t łączy model z jakimś n-tym modelem przechodzącym przez modele n-1 dla łatwiejszego dostępu. Czy jest coś jeszcze, czego mi brakuje oprócz skrótu?

Odpowiedz

47
  1. Logic, OK to może brzmieć trochę słaby na to, ale logiczne byłoby powiedzieć, że „mam dostawcę, który ma konto ze mną, chcę zobaczyć całą historię konta tego dostawca ", więc rozsądnie jest mieć możliwość bezpośredniego dostępu do historii rachunku od dostawcy.

  2. Efficiency, to dla mnie jest to główny powód, użyłbym :through, po prostu dlatego, że to wystawia dołączyć oświadczenie zamiast nazywając dostawcę, a następnie konto, a następnie account_history. zauważyłeś liczbę wywołań bazy danych?

    • użyciu :through, 1 wezwanie, aby dostawcy, 1 połączenie dostać account_history (szyny automatycznie używa :join odzyskać przez rachunek)

    • stosując normalne stowarzyszenie, 1 wezwanie, aby dostawcy, 1 wywołanie dostać konto i 1 wywołanie dostać account_history

to co myślę =) nadzieję, że to pomaga!

+2

Myślę, że argument logiczny jest całkiem poprawny. Brzmi bardziej naturalnie, powiedzmy, zdobądź historię konta tego dostawcy, a nie historię konta dostawcy. Bardzo subtelny, ale wciąż łatwiejszy do zapamiętania, biorąc pod uwagę filozofię płynących Ruby/Railsów niż kod. Wiem, że możemy zobaczyć faktyczne kwerendy DB są wydawane, ale czy Railsy określają, w jaki sposób te wywołania metody przełożyłoby się na SQL? – Anurag

+10

Pozwala to również uniknąć naruszenia prawa Demeter. –

+2

@TomCrayford, naprawdę nie wiem jak to działa. Czy to nie sprawia, że ​​relacja jest mniej bezpośrednia? –

6
  • Inverse stowarzyszenie: uważają, że łatwość obsługi członkostwie grupy klasyczny sytuacji. Jeśli użytkownik może być członkiem wielu grup, grupa ma wielu członków lub użytkowników, a użytkownik ma wiele grup. Ale jeśli użytkownik może być członkiem tylko w jednej grupie, grupa nadal ma wielu członków: class User has_one :group, :through => :membership, ale class Group has_many :members, :through => memberships. Model pośredni membership jest przydatny do śledzenia odwrotnej zależności.

  • rozbudowy: relacja has_one :through może być łatwo rozbudowany i przedłużony do has_many :through relacji

7

Dziwię nikt nie poruszył Stowarzyszenie Przedmioty.

has_many (lub has_one) :through związek ułatwia korzystanie z association object pattern który jest, gdy masz dwie rzeczy związane z sobą, i że sama relacja ma atrybuty (czyli datę, kiedy stowarzyszenie zostało wykonane lub gdy wygasa).

To jest considered by some, aby być dobrą alternatywą dla pomocnika ActiveRecord has_and_belongs_to_many. Rozumowanie tego jest takie, że jest bardzo prawdopodobne, że będziesz musiał zmienić charakter stowarzyszenia lub dodać do niego, a kiedy jesteś kilka miesięcy do projektu, może to być bardzo bolesne, jeśli związek został początkowo skonfigurowany jako a has_and_belongs_to_many (drugie łącze przechodzi w jakiś detal). Jeśli jest skonfigurowany początkowo przy użyciu relacji has_many :through, a następnie kilka miesięcy do projektu, łatwo zmienić nazwę modelu łączenia lub dodać do niego atrybuty, co ułatwia programistom reagowanie na zmieniające się wymagania. Zaplanuj zmianę.