एसोसिएट्स के माध्यम से अंतर्गत आता है


141

निम्नलिखित संघों को देखते हुए, मुझे Questionउस संदर्भ को संदर्भित करने की आवश्यकता है Choiceजो Choiceमॉडल से जुड़ा हुआ है । मैं belongs_to :question, through: :answerइस क्रिया को करने के लिए उपयोग करने का प्रयास कर रहा हूं ।

class User
  has_many :questions
  has_many :choices
end

class Question
  belongs_to :user
  has_many :answers
  has_one :choice, :through => :answer
end

class Answer
  belongs_to :question
end

class Choice
  belongs_to :user
  belongs_to :answer
  belongs_to :question, :through => :answer

  validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
end

मैं समझ रहा हूं

NameError uninitialized स्थिर User::Choice

जब मैं करने की कोशिश करता हूं current_user.choices

यह ठीक काम करता है, अगर मैं शामिल नहीं है

belongs_to :question, :through => :answer

लेकिन मैं इसका इस्तेमाल करना चाहता हूं क्योंकि मैं ऐसा करने में सक्षम होना चाहता हूं validates_uniqueness_of

मैं शायद कुछ सरल देख रहा हूँ। किसी भी सहायता की सराहना की जाएगी।


1
शायद यह प्रतिनिधि के लिए स्वीकृत उत्तर को बदलने के लायक है?
२३:११ पर २३

जवाबों:


60

एक belongs_toसंघ के पास कोई :throughविकल्प नहीं हो सकता। आप कैशिंग से बेहतर कर रहे हैं question_idपर Choiceऔर टेबल के लिए एक अनूठा सूचकांक जोड़ने (विशेष रूप से, क्योंकि validates_uniqueness_ofदौड़ की स्थिति की संभावना है)।

यदि आप पागल हैं, तो एक कस्टम सत्यापन जोड़ें Choiceजो इस बात की पुष्टि करता है कि उत्तर के question_idमैच, लेकिन ऐसा लगता है कि अंत उपयोगकर्ता को कभी भी डेटा जमा करने का अवसर नहीं दिया जाना चाहिए जो इस तरह का बेमेल निर्माण करेगा।


धन्यवाद स्टीफन, मैं वास्तव में question_id के साथ सीधे जुड़ना नहीं चाहता था, लेकिन मुझे इसका सबसे आसान तरीका लगता है। मेरा मूल विचार था, चूंकि "उत्तर" का संबंध "प्रश्न" से है, मैं हमेशा "प्रश्न" को पाने के लिए "उत्तर" से गुजर सकता हूं। लेकिन क्या आपको लगता है कि ऐसा करना आसान नहीं है, या आपको लगता है कि सिर्फ एक बुरा स्कीमा है?
15

यदि आप एक अद्वितीय बाधा / मान्यता चाहते हैं, तो स्कूप किए गए फ़ील्ड एक ही तालिका में मौजूद होने चाहिए। याद रखें, दौड़ की स्थिति हैं।
Stephencelis

1
>> ऐसा लगता है कि अंत उपयोगकर्ता को कभी भी डेटा प्रस्तुत करने का अवसर नहीं दिया जाना चाहिए जो इस प्रकार का बेमेल निर्माण करेगा। - आप कभी भी गारंटी नहीं दे सकते कि उपयोगकर्ता के पास "कुछ करने का अवसर नहीं है" जब तक आप उसके लिए एक स्पष्ट सर्वर-साइड जांच नहीं करते हैं।
कॉन्सटेंटिन

376

आप यह भी प्रतिनिधि कर सकते हैं:

class Company < ActiveRecord::Base
  has_many :employees
  has_many :dogs, :through => :employees
end

class Employee < ActiveRescord::Base
  belongs_to :company
  has_many :dogs
end

class Dog < ActiveRecord::Base
  belongs_to :employee

  delegate :company, :to => :employee, :allow_nil => true
end

27
+1, यह ऐसा करने का सबसे साफ तरीका है। (कम से कम जो मैं सोच सकता हूं)
ऑरलैंडो

9
क्या JOIN के साथ ऐसा करने का कोई तरीका है ताकि यह इतने सारे प्रश्नों का उपयोग न करे?
टॉलबॉय

1
मैं खुद को जानना चाहता हूं। सब कुछ मैंने कोशिश की 3 चयन निकाल दिया। आप एक एसोसिएशन पर "-> {जॉइन: कुछ}" लैम्बडा निर्दिष्ट कर सकते हैं। ज्वाइन को निकाल दिया गया है, लेकिन बाद में एक और चयन किया गया। मैं इसे धुन नहीं पा रहा था।
रेना

2
@ टैल्बॉय प्राथमिक कुंजी पर कुछ पूरी तरह से अनुक्रमित चुनिंदा प्रश्न लगभग किसी भी एकल क्वेरी क्वेरी से लगभग हमेशा बेहतर होते हैं। जॉइन डेटाबेस को कठिन बनाते हैं।
रयान मैक्ग्रे

1
Allow_nil क्या करता है? क्या एक कर्मचारी के पास हमेशा एक कंपनी नहीं होनी चाहिए?
अरोन-कोडिंग

115

बस अपने has_oneबजाय इस तरह का उपयोग करें:belongs_to:through

class Choice
  belongs_to :user
  belongs_to :answer
  has_one :question, :through => :answer
end

असंबंधित, लेकिन मैं आपके डेटाबेस में एक उचित अद्वितीय बाधा का उपयोग करने के बजाय validates_uniqueness_of का उपयोग करने में संकोच करूंगा। जब आप रूबी में ऐसा करते हैं तो आपके पास दौड़ की स्थिति होती है।


38
इस समाधान के साथ बड़ी चेतावनी। जब भी आप चॉइस सेव करते हैं तो यह हमेशा प्रश्न सेव करेगा जब तक autosave: falseकि सेट न हो।
क्रिस निकोला

@ क्रिसनीकोला क्या आप समझा सकते हैं कि आपका क्या मतलब है, मुझे समझ नहीं आया कि आपका क्या मतलब है।
अक्स

मेरा मतलब कहाँ था? यदि आप एक उचित विशिष्ट बाधा का अर्थ रखते हैं, तो मेरा मतलब है कि कॉलम / फ़ील्ड में एक अद्वितीय सूचकांक जोड़ना जो डेटाबेस में अद्वितीय होना चाहिए।
क्रिस निकोला

4

मेरा दृष्टिकोण डेटाबेस कॉलम जोड़ने के बजाय एक आभासी विशेषता बनाना था।

class Choice
  belongs_to :user
  belongs_to :answer

  # ------- Helpers -------
  def question
    answer.question
  end

  # extra sugar
  def question_id
    answer.question_id
  end
end

यह दृष्टिकोण बहुत सरल है, लेकिन ट्रेडऑफ़ के साथ आता है। इसे answerdb से लोड करने के लिए रेल की आवश्यकता होती है , और फिर question। इसे बाद में आपके द्वारा आवश्यक संघों (यानी c = Choice.first(include: {answer: :question})) को उत्सुकता से लोड करके अनुकूलित किया जा सकता है , हालांकि, यदि यह अनुकूलन आवश्यक है, तो स्टेफेनसेलिस का जवाब शायद बेहतर प्रदर्शन निर्णय है।

कुछ विकल्पों के लिए एक समय और स्थान है, और मुझे लगता है कि प्रोटोटाइप करते समय यह विकल्प बेहतर है। मैं इसे उत्पादन कोड के लिए उपयोग नहीं करूंगा जब तक कि मुझे पता न हो कि यह एक अनैतिक उपयोग के मामले में था।


1

ऐसा लगता है कि आप जो चाहते हैं वह एक उपयोगकर्ता है जिसके पास कई प्रश्न हैं।
प्रश्न के कई उत्तर हैं, जिनमें से एक उपयोगकर्ता की पसंद है।

क्या यह आप के बाद कर रहे हैं?

मैं इन लाइनों के साथ कुछ इस तरह का मॉडल तैयार करूंगा:

class User
  has_many :questions
end

class Question
  belongs_to :user
  has_many   :answers
  has_one    :choice, :class_name => "Answer"

  validates_inclusion_of :choice, :in => lambda { answers }
end

class Answer
  belongs_to :question
end

1

इसलिए आपके पास वह व्यवहार नहीं है जो आप चाहते हैं लेकिन आप कुछ ऐसा कर सकते हैं जो इसे पसंद करता है। आप करने में सक्षम होना चाहते हैंChoice.first.question

अतीत में मैंने जो किया है वह कुछ इस तरह है

class Choice
  belongs_to :user
  belongs_to :answer
  validates_uniqueness_of :answer_id, :scope => [ :question_id, :user_id ]
  ...
  def question
    answer.question
  end
end

इस तरह से अब आप चॉइस पर सवाल कर सकते हैं


-1

has_many :choicesएक संघ नामित बनाता है choices, नहीं choicecurrent_user.choicesइसके बजाय प्रयोग करके देखें ।

ActiveRecord ::has_many जादू के बारे में जानकारी के लिए संघों के दस्तावेज़ देखें ।


1
आपकी मदद के लिए धन्यवाद माइकल, हालांकि, मेरी ओर से एक टाइपो है। मैं पहले से ही कर रहा हूँ current_user.choices। इस त्रुटि का मुझे कुछ लेना देना है जो उपयोगकर्ता और प्रश्न से संबंधित है।
विन्ह्बॉय
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.