Rails'te "has_many: through" ilişkisi ne zaman kullanılır?


123

Neyin ne has_many :througholduğunu ve ne zaman (ve nasıl) kullanılacağını anlamaya çalışıyorum . Ancak, anlamıyorum. Beginning Rails 3 okuyorum ve Googling'i denedim, ancak anlayamıyorum.

Yanıtlar:


177

Diyelim ki iki modeliniz var: Userve Group.

Kullanıcıların gruplara üye olmasını istiyorsanız, bunun gibi bir şey yapabilirsiniz:

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

İlişkilendirme ile ilgili ek meta verileri izlemek isterseniz ne olur? Örneğin, kullanıcı gruba katıldığında veya belki de kullanıcının gruptaki rolü nedir?

Bu, ilişkilendirmeyi birinci sınıf bir nesne yaptığınız yerdir:

class GroupMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group

  # has attributes for date_joined and role
end

Bu, yeni bir tablo sunar ve group_idkullanıcının tablosundaki sütunu kaldırır .

Bu kodla ilgili sorun, kullanıcı sınıfını kullandığınız her yerde güncellemeniz ve değiştirmeniz gerektiğidir:

user.groups.first.name

# becomes

user.group_memberships.first.group.name

Bu tür bir kod berbattır ve bu gibi değişikliklerin yapılmasını acı verici hale getirir.

has_many :through size her iki dünyanın da en iyisini verir:

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

Artık buna normal bir davranış gibi davranabilir has_many, ancak ihtiyaç duyduğunuzda ilişkilendirme modelinden yararlanabilirsiniz.

Bunu ile de yapabileceğinizi unutmayın has_one.

Düzenleme: Bir gruba kullanıcı eklemeyi kolaylaştırma

def add_group(group, role = "member")
  self.group_associations.build(:group => group, :role => role)
end

2
userGrubu eklemek için modele bir yöntem ekleyeceğim yer burasıdır . Az önce yaptığım düzenleme gibi bir şey. Bu yardımcı olur umarım.
Ben Scheirman

Anlıyorum, benim de yazmak zorunda mıyım user.groups << group? Yoksa her şey bu dernek tarafından mı ele alınır?
LuckyLuke

Group_membership ile aynı olan bir sınıfım var ve bununla fabrika kızı kullanmakta sorun yaşıyorum bana yardımcı olur musun?
Ayman Salah

"Has_many: group_memberships" kullanırım. Tekil kullanmak işe yarayacak, ancak user.group_membership bir koleksiyon olacak ve user.group_memberships çalışmayacak.
calasyr

Bu bir yazım hatasıydı. Sabit.
Ben Scheirman

212

Şu modellere sahip olduğunuzu varsayalım:

Car
Engine
Piston

Bir araba has_one :engine
Bir motor belongs_to :car
Bir motorhas_many :pistons
Pistonbelongs_to :engine

Araba has_many :pistons, through: :engine
Pistonuhas_one :car, through: :engine

Esasen başka modele model ilişkisi devrederek, bu yüzden yerine çağrıya sahip car.engine.pistons, sadece yapabilirsinizcar.pistons


9
Bu çok mantıklı!
RajG

24
Ben buna SACA - ShortAndClearAnswer diyorum.
Asme Sadece

18

ActiveRecord Tabloları Birleştirme

has_many :throughve has_and_belongs_to_manyilişkiler yoluyla işlev birleştirme tablosunda diğer tabloları arasındaki ilişkiyi temsil eden bir ara tablodur. Bir JOIN sorgusundan farklı olarak, veriler aslında bir tabloda saklanır.

Pratik Farklılıklar

İle has_and_belongs_to_many , birincil anahtara ihtiyacınız yoktur ve kayıtlara bir ActiveRecord modeli yerine ActiveRecord ilişkileri aracılığıyla erişirsiniz. İki modeli çoka çok ilişkisine bağlamak istediğinizde genellikle HABTM kullanırsınız.

has_many :throughBirleştirme tablosuyla bir Rails modeli olarak etkileşim kurmak istediğinizde, birincil anahtarlarla ve birleştirilen verilere özel sütunlar ekleme becerisiyle birlikte bir ilişki kullanırsınız. İkincisi, birleştirilen satırlarla ilgili olan, ancak gerçekten ilgili modellere ait olmayan veriler için özellikle önemlidir - örneğin, birleştirilmiş satırdaki alanlardan türetilen hesaplanmış bir değeri depolamak.

Ayrıca bakınız

In Active kayıt Dernekler A Guide , öneri okur:

En basit kural, ilişki modeliyle bağımsız bir varlık olarak çalışmanız gerekiyorsa, has_many: ilişki yoluyla kurmanız gerektiğidir. İlişki modeliyle herhangi bir şey yapmanız gerekmiyorsa, has_and_belongs_to_many ilişkisi kurmak daha basit olabilir (ancak veritabanında birleştirme tablosunu oluşturmayı hatırlamanız gerekecektir).

Birleştirme modelinde doğrulamalara, geri aramalara veya ekstra özniteliklere ihtiyacınız varsa, has_many: through kullanmalısınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.