has_many'ye kayıtlar nasıl eklenir: raylardaki ilişkilendirme yoluyla


97
class Agents << ActiveRecord::Base
  belongs_to :customer
  belongs_to :house
end

class Customer << ActiveRecord::Base
  has_many :agents
  has_many :houses, through: :agents
end

class House << ActiveRecord::Base
  has_many :agents
  has_many :customers, through: :agents
end

İçin Agentsmodele nasıl eklerim Customer?

En iyi yol bu mu?

Customer.find(1).agents.create(customer_id: 1, house_id: 1)

Yukarıdakiler konsoldan iyi çalışıyor, ancak bunu gerçek uygulamada nasıl başaracağımı bilmiyorum.

Müşteri için aynı zamanda house_idgirdi alan bir formun doldurulduğunu hayal edin . Sonra kontrol cihazımda aşağıdakileri yapar mıyım?

def create 
  @customer = Customer.new(params[:customer])
  @customer.agents.create(customer_id: @customer.id, house_id: params[:house_id])
  @customer.save
end

Genel olarak has_many :throughtabloya kayıtların nasıl ekleneceği konusunda kafam karıştı mı?


Oluşturma işlevini hangi denetleyicide saklarsınız?
Tobias Kolb

Yanıtlar:


166

Sanırım bunu kolayca yapabilirsiniz:

 @cust = Customer.new(params[:customer])
 @cust.houses << House.find(params[:house_id])

Veya bir müşteri için yeni bir ev oluştururken:

 @cust = Customer.new(params[:customer])
 @cust.houses.create(params[:house])

Ayrıca kimlikler aracılığıyla da ekleyebilirsiniz:

@cust.house_ids << House.find(params[:house_id])

16
Bilginize: Ebeveyn önceden kaydedilmedikçe ilişkili evi oluşturamazsınız.
Ricardo Otero

Karşılaştığım bu soruna en zarif çözüm bu olmalı. +1 sizin için.
Daniel Bonnell

Ben Kullanabileceğimiz tahmin @RicardoOtero buildarasında Istead create?
Karan

@Mischa House.find (params [: house_id]) boşsa hatayı nasıl ele almalıyım .. params [: house_id] sıfırsa TypeMismatch hatası aldım .. zaten rescue kullanıyorum. ama daha iyi bir yol var mı?
Vishal

1
<<Operatör kullanmanın belirli durumlarda iki kez ekleme yaptığını gözlemledim . Yani createyöntem en iyi yoldur.
takas

79

'En iyi yol' ihtiyaçlarınıza ve neyin en rahat hissettirdiğine bağlıdır. Karışıklık, ActiveRecord'un newve createyöntemleri ve <<operatör davranışlarındaki farklılıklardan kaynaklanır .

newYöntem

newsizin için bir ilişkilendirme kaydı eklemeyecektir. HouseVe Agentkayıtlarını kendiniz oluşturmanız gerekir :

house = @cust.houses.new(params[:house])
house.save
agent = Agent(customer_id: @cust.id, house_id: house.id)
agent.save

Not olduğunu @cust.houses.newve House.newoluşturmak gerekir çünkü etkili bir şekilde aynıdır Agenther iki durumda da rekor.

<<Operatör

Mischa'nın bahsettiği gibi, <<operatörü koleksiyonda da kullanabilirsiniz . Bu sadece Agentmodeli sizin için oluşturacaktır, Housemodeli oluşturmanız gerekir :

house = House.create(params[:house])
@cust.houses << house
agent = @cust.houses.find(house.id)

createYöntem

createhem inşa edecek Houseve Agentsizin için kayıtlar, ancak bulmanız gerekir AgentEğer görünüm veya api'sine o dönmek niyetinde olmadığını modeli:

house = @cust.houses.create(params[:house])
agent = @cust.agents.where(house: house.id).first

Son bir not olarak, oluştururken istisnaların ortaya çıkmasını istiyorsanız house, bunun yerine patlama operatörlerini kullanın (örneğin new!ve create!).


2
Bunun yerine satır agent = @cust.houses.find(house.id)okunmalı agent = @cust.agents.find(house.id)mı? agent"Yeni Yöntemi" değişken farklıdır agentSonraki örneklerde. Birleştirme tablosunda ek özelliklerle çalışan kişiler için biraz kafa karışıklığı yaratabilir.
vaughan

Belirli bir müşteri için tüm evleri ve karşılık gelen aracıları görüntüleyen N + 1 hata örneğine sahip olmadan Ajanlar ortak tablosundan veri alma konusunda ayrıntılı bilgi verebilir misiniz
Ankita.P

6

İlişkilendirme eklemenin başka bir yolu, yabancı anahtar sütunlarını kullanmaktır:

agent = Agent.new(...)
agent.house = House.find(...)
agent.customer = Customer.find(...)
agent.save

Veya tam sütun adlarını kullanın, kayıt yerine ilişkili kaydın kimliğini iletin.

agent.house_id = house.id
agent.customer_id = customer.id
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.