2010-01-25 12 views
17

मेरे पास एक मॉडल है जो Content आइटम का प्रतिनिधित्व करता है जिसमें कुछ छवियां होती हैं। छवियों की संख्या तय की गई है क्योंकि ये छवि संदर्भ सामग्री के लिए बहुत विशिष्ट हैं। उदाहरण के लिए, Content मॉडल Image मॉडल को दो बार (प्रोफ़ाइल छवि, और पृष्ठभूमि छवि) से संदर्भित करता है। मैं एक सामान्य has_many से बचने की कोशिश कर रहा हूं, और कई has_one पर चिपक रहा हूं। वर्तमान डेटाबेस संरचना इस तरह दिखती है:रेल के पास है_ऑन बनाम सेमेन्टिक्स

contents 
    - id:integer 
    - integer:profile_image_id 
    - integer:background_image_id 

images 
    - integer:id 
    - string:filename 
    - integer:content_id 

मैं यह नहीं समझ सकता कि संघों को सही तरीके से कैसे सेटअप किया जाए। Content मॉडल में Image के संदर्भों में दो belongs_to संदर्भ हो सकते हैं, लेकिन यह वास्तव में सामग्री के अंतर्गत आता है, या दूसरे शब्दों में, अर्थात् सही छवि प्रतीत नहीं होता है, सामग्री में दो छवियां होती हैं।

यह (अर्थ विज्ञान तोड़कर) सबसे अच्छा मैं के बारे में सोच सकता है:

class Content 
    belongs_to :profile_image, :class_name => 'Image', :foreign_key => 'profile_image_id' 
    belongs_to :background_image, :class_name => 'Image', :foreign_key => 'background_image_id' 
end 

मैं जिस तरह से बंद इस संघ को प्राप्त करने के लिए एक बेहतर तरीका हूँ, और वहाँ?

उत्तर

22

सरल उत्तर सेटअप करने के लिए आपके पास क्या है, इसलिए तरह की रिवर्स में अपने संघों है ।

हालांकि, एक और अधिक सुरुचिपूर्ण समाधान है: एकल तालिका विरासत। यदि आप पृष्ठभूमि और प्रोफ़ाइल छवियों को भविष्य में थोड़ा अलग तरीके से व्यवहार करना चाहते हैं, तो इसे अभी सेट करें, साथ ही यह आज आपके कोड को स्पष्ट करेगा।अपने मॉडल इस तरह

# command line 
script/generate migration AddTypeToImages type:string 
rake db:migrate 

अब सेटअप: की सूची प्राप्त करने की तरह

# app/models/content.rb 
class Content < ActiveRecord::Base 
    has_one :profile_image 
    has_one :background_image 
end 

# app/models/image.rb 
class Image < ActiveRecord::Base 
    belongs_to :content 
end 

# app/models/background_image.rb 
class BackgroundImage < Image 
    # background image specific code here 
end 

# app/models/profile_image.rb 
class ProfileImage < Image 
    # profile image specific code here 
end 

अब आप चीजों के सभी प्रकार कर सकते हैं

सबसे पहले, एक स्तंभ अपने चित्रों को तालिका प्रकार कहा जाता जोड़ने सभी पृष्ठभूमि छवियां:

# script/console 
BackgroundImage.all 

यह डेटा मॉडल के लिए अधिक सत्य है जिसे आप बनाने की कोशिश कर रहे हैं, भविष्य में सबसे आसान विस्तारशीलता की अनुमति देता है, और आपको आज कुछ शानदार नई विधियां देता है।

अद्यतन:

मैंने के बाद से एक ब्लॉग लेख Single-Table Inheritance with Tests कहा जाता है कि और अधिक विस्तार में चला जाता है, और परीक्षण को शामिल किया गया बनाया।

+0

सिंगल टेबल विरासत मेरी समस्या के लिए पूरी तरह से काम करता है। क्या आप जानते हैं कि मैं पॉलिमॉर्फिक एसोसिएशन के साथ एसटीआई को कैसे एकीकृत करूं? उदाहरण के लिए, यदि सामग्री के साथ, कुछ छवियां थीं जो दस्तावेज़ मेटाडेटा का हिस्सा थीं, और दोनों - सामग्री और मेटाडेटा छवियों को छवि तालिका में संग्रहीत किया गया था। – Anurag

+0

लेख के लिए बहुत बहुत धन्यवाद। नेट पर रेल के लिए सिंगल टेबल विरासत पर सबसे अच्छा लेख होना चाहिए! – Anurag

+0

'सरल उत्तर' के लिए, सामग्री को कैसे पता चलेगा कि छवियों को संदर्भित करने के लिए यदि उसकी डीबी तालिका में कोई विदेशी कुंजी नहीं है? – greg7gkb

1

the AR associations guide के आधार पर, मुझे लगता है कि आपको has_one का उपयोग करना चाहिए। किसी छवि के लिए सामग्री के स्वामित्व में यह समझ में नहीं आता है ... सामग्री निश्चित रूप से छवि का मालिक है। गाइड से:

भेद में जहां विदेशी कुंजी जगह (यह वर्ग belongs_to संघ घोषित करने के लिए तालिका पर चला जाता है) है, लेकिन आप के वास्तविक अर्थ को कुछ विचार कर लेना चाहिए डेटा भी। हैसोन रिलेशनशिप कहता है कि कुछ में से एक तुम्हारा है - यह है कि कुछ पर वापस आता है।

अंत में, मुझे यकीन है कि आप दोनों सामग्री और छवियों विदेशी कुंजी की आवश्यकता नहीं हूँ। जब तक छवियां content_id का संदर्भ देती हैं, मुझे लगता है कि आप ठीक हैं।

# app/models/content.rb 
class Content < ActiveRecord::Base 
    has_one :profile_image, :class_name => 'Image' 
    has_one :background_image, :class_name => 'Image' 
end 

# app/models/image.rb 
class Image < ActiveRecord::Base 
    belongs_to :content 
end 

आप सभी पर विदेशी कुंजी 'background_image_id' और सामग्री तालिका में 'profile_image_id' की जरूरत नहीं है:

संबंधित मुद्दे