has_many में रिकॉर्ड कैसे जोड़ें: रेल में एसोसिएशन के माध्यम से


94
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

मैं Agentsमॉडल के लिए कैसे जोड़ूँ Customer?

क्या यह सबसे अच्छा तरीका है?

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

ऊपर कंसोल से ठीक काम करता है, लेकिन मुझे नहीं पता कि वास्तविक एप्लिकेशन में इसे कैसे प्राप्त किया जाए।

कल्पना कीजिए कि ग्राहक के लिए एक फॉर्म भरा जाता है house_idजो इनपुट के रूप में भी लेता है । फिर क्या मैं अपने नियंत्रक में निम्नलिखित कार्य कर सकता हूं?

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

कुल मिलाकर मुझे भ्रम है कि has_many :throughतालिका में रिकॉर्ड कैसे जोड़ा जाए ?


आप किस कंट्रोलर में फंक्शन को "create" स्टोर करेंगे?
टोबियास कोलब

जवाबों:


163

मुझे लगता है कि आप बस यह कर सकते हैं:

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

या ग्राहक के लिए नया घर बनाते समय:

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

आप आईडी के माध्यम से भी जोड़ सकते हैं:

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

16
FYI करें: आप संबद्ध घर तब तक नहीं बना सकते जब तक कि माता-पिता पहले से ही सुरक्षित न हों।
रिकार्डो ओटेरो

मुझे इस समस्या का सबसे सुंदर समाधान बनना है। आपके लिए +1।
डैनियल बॉननेल

@RicardoOtero मुझे लगता है कि हम buildistead का उपयोग कर सकते हैं create?
करण

@Mischa मैं कैसे त्रुटि को संभालना चाहिए अगर House.find (params [: house_id]) nill है .. मुझे टाइपमैस्मैच की त्रुटि मिली अगर params [: house_id] nil है .. तो मैं पहले से ही बचाव का उपयोग कर रहा हूं। लेकिन क्या कोई better_way है .. ??
विशाल

1
मैंने देखा है कि <<ऑपरेटर का उपयोग कुछ मामलों में दो बार सम्मिलन करता है। तो createविधि सबसे अच्छा तरीका है।
स्वैप

77

'सबसे अच्छा तरीका' आपकी आवश्यकताओं पर निर्भर करता है और जो सबसे अधिक आरामदायक लगता है। भ्रम ActiveRecord के व्यवहार newऔर createविधियों और <<ऑपरेटर के अंतर से आता है ।

newविधि

newआपके लिए एक एसोसिएशन रिकॉर्ड नहीं जोड़ेगा। आपको स्वयं का निर्माण करना होगा Houseऔर Agentरिकॉर्ड करना होगा:

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

ध्यान दें कि @cust.houses.newऔर House.newप्रभावी रूप से समान हैं क्योंकि आपको Agentदोनों मामलों में रिकॉर्ड बनाने की आवश्यकता है ।

<<ऑपरेटर

जैसा कि मिशा उल्लेख करते हैं, आप <<संग्रह पर ऑपरेटर का उपयोग भी कर सकते हैं । यह केवल Agentआपके लिए मॉडल का निर्माण करेगा , आपको Houseमॉडल का निर्माण करना होगा :

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

createविधि

createआपके लिए Houseऔर Agentरिकॉर्ड दोनों का निर्माण करेगा , लेकिन आपको Agentमॉडल ढूंढने की आवश्यकता होगी यदि आप इसे अपने विचार या एपीआई पर वापस करने का इरादा रखते हैं:

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

अंतिम नोट के रूप में, यदि आप चाहते houseहैं कि बैंग ऑपरेटरों का उपयोग करते समय (जैसे new!और create!) उपयोग करते समय अपवाद उठाए जाएं ।


2
क्या इसके बजाय लाइन agent = @cust.houses.find(house.id)पढ़नी agent = @cust.agents.find(house.id)चाहिए? agent"नई विधि" में चर के लिए अलग है agentउत्तरार्द्ध उदाहरण में। जॉइनिंग टेबल पर अतिरिक्त विशेषताओं के साथ काम करने वाले लोगों के लिए कुछ भ्रम पैदा कर सकता है।
विघ्न

क्या आप दिए गए ग्राहक के लिए सभी घरों और संबंधित एजेंटों को प्रदर्शित करते हुए N + 1 बग उदाहरण के बिना संयुक्त तालिका एजेंटों से डेटा प्राप्त करने पर विस्तृत कर सकते हैं
अंकिता।

6

संघों को जोड़ने का एक अन्य तरीका विदेशी कुंजी कॉलम का उपयोग करना है:

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

या सटीक स्तंभ नामों का उपयोग करें, रिकॉर्ड के बजाय संबंधित रिकॉर्ड की आईडी पास करना।

agent.house_id = house.id
agent.customer_id = customer.id
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.