रेल के संबंध में "has_many: through" का उपयोग कब करें?


123

मैं यह समझने की कोशिश कर रहा हूं कि has_many :throughइसका क्या और कब उपयोग करना है (और कैसे)। हालांकि, मुझे यह नहीं मिल रहा है। मैं शुरुआती रेल 3 पढ़ रहा हूं और मैंने Googling की कोशिश की, लेकिन मैं समझ नहीं पा रहा हूं।

जवाबों:


177

मान लें कि आपके पास दो मॉडल हैं: UserऔरGroup

यदि आप चाहते थे कि उपयोगकर्ता समूहों से संबंधित हों, तो आप कुछ इस तरह से कर सकते हैं:

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

यदि आप एसोसिएशन के आसपास अतिरिक्त मेटाडेटा ट्रैक करना चाहते हैं तो क्या होगा? उदाहरण के लिए, जब उपयोगकर्ता समूह में शामिल हुआ, या शायद उपयोगकर्ता की समूह में क्या भूमिका है?

यह वह जगह है जहाँ आप एसोसिएशन को एक प्रथम श्रेणी वस्तु बनाते हैं:

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

  # has attributes for date_joined and role
end

यह एक नई तालिका पेश करता है, और group_idउपयोगकर्ता की तालिका से कॉलम को समाप्त करता है ।

इस कोड के साथ समस्या यह है कि आपको हर उस जगह को अपडेट करना होगा जहां आप उपयोगकर्ता वर्ग का उपयोग करते हैं और इसे बदलते हैं:

user.groups.first.name

# becomes

user.group_memberships.first.group.name

इस प्रकार का कोड बेकार है, और यह इस दर्दनाक की तरह परिवर्तन शुरू करता है।

has_many :through आपको दोनों दुनिया का सर्वश्रेष्ठ देता है:

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

अब आप इसे सामान्य की तरह मान सकते हैं has_many, लेकिन जरूरत पड़ने पर एसोसिएशन मॉडल का लाभ उठा सकते हैं।

ध्यान दें कि आप भी ऐसा कर सकते हैं has_one

संपादित करें: उपयोगकर्ता को समूह में जोड़ना आसान बनाता है

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

2
यह वह जगह है जहां मैं userसमूह को जोड़ने के लिए मॉडल पर एक विधि जोड़ूंगा। मेरे द्वारा किए गए संपादन जैसा कुछ। उम्मीद है की यह मदद करेगा।
बेन शाहीरमैन

देखता हूं, क्या मुझे भी लिखना है user.groups << group? या सब कुछ इस संघ द्वारा संभाला जाता है?
लकीलुक जुले

मेरे पास एक वर्ग है जो group_membership के समान है और मुझे कारखाने की लड़की का उपयोग करने में कोई समस्या हो रही है, क्या इससे मुझे मदद मिलेगी?
अयमान सलाह

मैं "has_many: group_memberships" का उपयोग करता हूं। एकवचन का उपयोग करने से काम चलेगा, लेकिन user.group_membership एक संग्रह और user.group_membership काम नहीं करेगा।
कैलासीर

वह एक टाइपो था। फिक्स्ड।
बेन शीशमैन

212

कहो कि आपके पास ये मॉडल हैं:

Car
Engine
Piston

एक कार has_one :engine
एक इंजन belongs_to :car
एक इंजनhas_many :pistons
पिस्टनbelongs_to :engine

एक गाडी has_many :pistons, through: :engine
पिस्टनhas_one :car, through: :engine

अनिवार्य रूप से आप एक मॉडल रिश्ते को दूसरे मॉडल में सौंप रहे हैं, इसलिए कॉल करने के बजाय car.engine.pistons, आप बस कर सकते हैंcar.pistons


9
यह पूरी तरह से समझ में आता है!
राजग

24
मैं इस SACA - ShortAndClearAnswer को कॉल करता हूं।
असीम जस्ट

18

ActiveRecord टेबल्स में शामिल हों

has_many :throughऔर has_and_belongs_to_manyरिश्तों में शामिल होने की मेज के माध्यम से कार्य , जो एक मध्यवर्ती तालिका है जो अन्य तालिकाओं के बीच संबंधों का प्रतिनिधित्व करती है। JOIN क्वेरी के विपरीत, डेटा वास्तव में एक तालिका में संग्रहीत किया जाता है।

व्यावहारिक अंतर

इसके साथ has_and_belongs_to_many, आपको एक प्राथमिक कुंजी की आवश्यकता नहीं है, और आप ActiveRecord मॉडल के बजाय ActiveRecord संबंधों के माध्यम से रिकॉर्ड एक्सेस करते हैं। आप आमतौर पर HABTM का उपयोग तब करते हैं जब आप दो मॉडलों को कई-कई संबंधों से जोड़ना चाहते हैं।

आप एक का उपयोग करें has_many :through संबंध का तब करते हैं जब आप एक रैल मॉडल के रूप में ज्वाइन टेबल के साथ बातचीत करना चाहते हैं, प्राथमिक कुंजियों के साथ पूर्ण होते हैं और जुड़ने वाले डेटा में कस्टम कॉलम जोड़ने की क्षमता होती है। उत्तरार्द्ध विशेष रूप से उन डेटा के लिए महत्वपूर्ण है जो सम्मिलित पंक्तियों के लिए प्रासंगिक है, लेकिन वास्तव में संबंधित मॉडल से संबंधित नहीं है - उदाहरण के लिए, सम्मिलित पंक्ति में फ़ील्ड से प्राप्त परिकलित मान संग्रहीत करना।

यह सभी देखें

में सक्रिय रिकॉर्ड संघों के लिए एक गाइड , सिफारिश पर लिखा है:

अंगूठे का सबसे सरल नियम यह है कि आपको एक has_many सेट करना चाहिए: यदि आपको एक स्वतंत्र इकाई के रूप में संबंध मॉडल के साथ काम करने की आवश्यकता है, तो संबंध के माध्यम से। यदि आपको रिलेशनशिप मॉडल के साथ कुछ करने की आवश्यकता नहीं है, तो has_and_belongs_to_many संबंध स्थापित करना आसान हो सकता है (हालाँकि आपको डेटाबेस में शामिल होने वाली तालिका बनाने के लिए याद रखने की आवश्यकता होगी)।

आपको has_many का उपयोग करना चाहिए: यदि आपको जुड़ने वाले मॉडल पर सत्यापन, कॉलबैक या अतिरिक्त विशेषताओं की आवश्यकता है।

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