Próbuję zrozumieć, czym has_many :through
jest i kiedy (i jak) tego używać. Jednak nie rozumiem. Czytam Beginning Rails 3 i próbowałem googlować, ale nie jestem w stanie tego zrozumieć.
źródło
Próbuję zrozumieć, czym has_many :through
jest i kiedy (i jak) tego używać. Jednak nie rozumiem. Czytam Beginning Rails 3 i próbowałem googlować, ale nie jestem w stanie tego zrozumieć.
Powiedzmy, że masz dwa modele: User
i Group
.
Jeśli chciałbyś, aby użytkownicy należeli do grup, możesz zrobić coś takiego:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
A co by było, gdybyś chciał śledzić dodatkowe metadane wokół powiązania? Na przykład, kiedy użytkownik dołączył do grupy, a może jaka jest rola użytkownika w grupie?
Tutaj tworzysz asocjację jako obiekt pierwszej klasy:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
Wprowadza to nową tabelę i eliminuje group_id
kolumnę z tabeli użytkownika.
Problem z tym kodem polega na tym, że musiałbyś zaktualizować każde inne miejsce, w którym używasz klasy użytkownika, i zmienić ją:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
Ten typ kodu jest do bani i sprawia, że wprowadzanie takich zmian jest bolesne.
has_many :through
daje to, co najlepsze z obu światów:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
Teraz możesz traktować to jak normalne has_many
, ale skorzystaj z modelu asocjacyjnego, gdy go potrzebujesz.
Pamiętaj, że możesz to również zrobić za pomocą has_one
.
Edycja: ułatwianie dodawania użytkownika do grupy
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user
modelu, aby dodać grupę. Coś jak zmiana, którą właśnie zrobiłem. Mam nadzieję że to pomoże.user.groups << group
? A może wszystkim zajmuje się to stowarzyszenie?Powiedzmy, że masz te modele:
Samochód
has_one :engine
Silnik
belongs_to :car
Silnik
has_many :pistons
Tłok
belongs_to :engine
Samochód
has_many :pistons, through: :engine
tłokowy
has_one :car, through: :engine
Zasadniczo delegujesz relację modelu do innego modelu, więc zamiast dzwonić
car.engine.pistons
, możesz to zrobićcar.pistons
źródło
ActiveRecord Join Tables
has_many :through
ihas_and_belongs_to_many
relacje funkcjonują za pośrednictwem tabeli łączenia , która jest tabelą pośrednią reprezentującą relacje między innymi tabelami. W przeciwieństwie do zapytania JOIN dane są w rzeczywistości przechowywane w tabeli.Praktyczne różnice
Dzięki temu
has_and_belongs_to_many
nie potrzebujesz klucza podstawowego i uzyskujesz dostęp do rekordów za pośrednictwem relacji ActiveRecord, a nie za pośrednictwem modelu ActiveRecord. Zwykle używasz HABTM, gdy chcesz połączyć dwa modele relacją wiele do wielu.Używasz
has_many :through
relacji, gdy chcesz współdziałać z tabelą złączeń jako modelem Rails, wraz z kluczami podstawowymi i możliwością dodawania niestandardowych kolumn do połączonych danych. To ostatnie jest szczególnie ważne w przypadku danych, które są istotne dla połączonych wierszy, ale tak naprawdę nie należą do powiązanych modeli - na przykład przechowywanie obliczonej wartości pochodzącej z pól w połączonym wierszu.Zobacz też
W Przewodniku po stowarzyszeniach Active Record rekomendacja brzmi:
źródło