समझ: पटरियों के माध्यम से has_one / has_many का स्रोत विकल्प


184

कृपया संघ के :sourceविकल्प को समझने में मेरी मदद करें has_one/has_many :through। रेल एपीआई स्पष्टीकरण मेरे लिए बहुत कम मायने रखता है।

"निर्दिष्ट करता है कि स्रोत संघ नाम से इस्तेमाल किया has_many :through => :queries। केवल इसका इस्तेमाल नाम संघ से नहीं लगाया जा सकता है। has_many :subscribers, :through => :subscriptionsया तो के लिए दिखेगा :subscribersया :subscriberपर Subscription, जब तक कि एक :sourceदिया जाता है।"

जवाबों:


238

कभी-कभी, आप अलग-अलग संघों के लिए अलग-अलग नामों का उपयोग करना चाहते हैं। यदि आप मॉडल पर एसोसिएशन के लिए जिस नाम का उपयोग करना चाहते हैं, वह मॉडल पर दिए गए आश्वाशन के समान नहीं है :through, तो आप :sourceइसे निर्दिष्ट करने के लिए उपयोग कर सकते हैं ।

मुझे नहीं लगता कि उपरोक्त अनुच्छेद डॉक्स में एक की तुलना में बहुत स्पष्ट है, इसलिए यहां एक उदाहरण है। मान लेते हैं कि हमारे पास तीन मॉडल हैं Pet, Dogऔर Dog::Breed

class Pet < ActiveRecord::Base
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :pet
  has_many :breeds
end

class Dog::Breed < ActiveRecord::Base
  belongs_to :dog
end

इस मामले में, हमने नाम स्थान को चुना है Dog::Breed, क्योंकि हम Dog.find(123).breedsएक अच्छे और सुविधाजनक संघ के रूप में पहुंचना चाहते हैं ।

अब, अगर हम अब एक has_many :dog_breeds, :through => :dogsएसोसिएशन बनाना चाहते हैं, तो हमें Petअचानक एक समस्या है। रेल :dog_breedsपर एक एसोसिएशन खोजने में सक्षम नहीं होगा Dog, इसलिए रेल संभवतः यह नहीं जान सकती कि आप किस Dog एसोसिएशन का उपयोग करना चाहते हैं। दर्ज करें :source:

class Pet < ActiveRecord::Base
  has_many :dogs
  has_many :dog_breeds, :through => :dogs, :source => :breeds
end

के साथ :source, हम रेल को मॉडल पर बुलाया एसोसिएशन के:breedsDog लिए देखने के लिए कह रहे हैं (जैसा कि मॉडल के लिए उपयोग किया जाता है :dogs), और उस का उपयोग करें।


2
मुझे लगता है कि आप अपने पिछले वर्ग के पशु का मतलब क्लास पेट कहलाना चाहते हैं, बस एक टाइपो मुझे विश्वास है।
Kamilski81

3
उपरोक्त उदाहरण में, संघ के तहत होना चाहिए Dogहोना has_many :breedबजाय :breedsऔर फिर :sourceजा :breedविलक्षण, मॉडल का नाम का प्रतिनिधित्व करने, के बजाय :breedsतालिका नाम का प्रतिनिधित्व करता है जो? जैसे has_many :dog_breeds, :through => :dogs, :source => :breed(कोई sप्रत्यय नहीं :breed)?
लेज़रशेक्स

1
मैंने इसका परीक्षण किया है। यह विलक्षण है, कोई sप्रत्यय नहीं है:source =>
अनवर

"इस मामले में, हमने डॉग को नाम स्थान देने का चयन किया है :: नस्ल, क्योंकि हम डॉग.फ़ीड (123) का उपयोग करना चाहते हैं। एक अच्छे और सुविधाजनक संघ के रूप में।" आपको इसके लिए किसी नामस्थान की आवश्यकता नहीं है?
16

200

मुझे उस उदाहरण पर विस्तार करने दें:

class User
  has_many :subscriptions
  has_many :newsletters, :through => :subscriptions
end

class Newsletter
  has_many :subscriptions
  has_many :users, :through => :subscriptions
end

class Subscription
  belongs_to :newsletter
  belongs_to :user
end

इस कोड के साथ, आप Newsletter.find(id).usersन्यूज़लेटर के ग्राहकों की सूची प्राप्त करने के लिए कुछ कर सकते हैं । लेकिन अगर आप स्पष्ट होना चाहते हैं और Newsletter.find(id).subscribersइसके बजाय टाइप करना चाहते हैं, तो आपको न्यूज़लैटर क्लास को इसमें बदलना होगा:

class Newsletter
  has_many :subscriptions
  has_many :subscribers, :through => :subscriptions, :source => :user
end

आप usersएसोसिएशन का नाम बदल रहे हैं subscribers। यदि आप प्रदान नहीं करते हैं :source, तो रेल subscriberसदस्यता वर्ग में एक एसोसिएशन की तलाश करेगी । आपको यह बताना होगा कि userग्राहकों की सूची बनाने के लिए सदस्यता वर्ग में एसोसिएशन का उपयोग करें ।


2
ध्यान दें कि, एकवचन मॉडल नामों का उपयोग किया जाना चाहिए :source =>, बहुवचन में नहीं। इसलिए, :usersगलत है, :userसही है
अनवर

यह सबसे अच्छा उत्तर है! मुझे इस भाग पर ज़ोर देने दें: "आप ग्राहकों के लिए उपयोगकर्ता एसोसिएशन का नाम बदल रहे हैं। यदि आप: स्रोत उपलब्ध नहीं कराते हैं, तो रेल्स सब्सक्रिप्शन क्लास में ग्राहक नामक एसोसिएशन की तलाश करेंगे।"
ब्रायन जोसेफ स्पिनोस

11

सबसे सरल उत्तर:

बीच में टेबल में रिश्ते का नाम है।

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