2009-07-06 14 views
5

मेरे पास दो मचान-जेनरेट मॉडल हैं, छात्र और कक्षा। उनके पास has_and_belongs_to_many के साथ लागू कई से अधिक संबंध हैं।
मैं बदलने के लिए जो वर्ग एक छात्र रूप में अच्छी तरह है जो के रूप में छात्र रों प्रत्येक वर्ग ले जा रहे हैं es सक्षम होने के लिए करना चाहते हैं। यही है, मैं छात्र के कक्षा परिवर्तनीय (इसमें से आइटम जोड़ने और निकालने) को संशोधित करना चाहता हूं और इसके विपरीत।
मैं इसे कैसे कर सकता हूं?
मैं कक्षाएं सूची एक छात्र से एक वर्ग को हटाने कर रहा हूँ, तो ऐसा लगता है जैसे मैं अपने students_controller पर अद्यतन कॉल करना चाहते हैं। यदि यह मामला है, तो कक्षा चर को संशोधित करने के लिए पैरामीटर के रूप में मुझे क्या पास करना चाहिए? वर्ग es का एक और संग्रह (उचित वर्ग हटा दिया गया है)?
मेरा दूसरा विचार केवल छात्रों_कंट्रोलर (कहें, remove_class) में कुछ कार्रवाई करने के लिए है और हटाए जाने के लिए कक्षा की आईडी में पास करें। यह सनसनीखेज लगता है लेकिन भरोसेमंद नहीं है।मैं एक हैश_and_belongs_to_many संग्रह को अद्यतन कैसे अपडेट करूं?

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

उत्तर

8

इस को हल करने के लिए कुंजी सही तरीके से संसाधन आप संशोधित कर रहे हैं की पहचान करना है के रूप में इस्तेमाल किया जाना चाहिए। इस मामले में, जिस संसाधन को आप संशोधित कर रहे हैं वह वर्ग और छात्र के बीच संबंध है, जिसे मैं Enrollment के रूप में संदर्भित करता हूं।

यह has_many :through को has_and_belongs_to_many पर अधिमानतः उपयोग करने के लिए रेल में प्रथा बन गया है। आप अपने डोमेन तर्क को कस्टम फिट करने के लिए बदल सकते हैं, लेकिन आप प्रवृत्ति को भी कम कर सकते हैं, अगर आप वास्तव में निश्चित हैं कि संबंध के बारे में कोई मेटाडेटा संग्रहीत करने की आवश्यकता नहीं है।

बाकी के लिए महत्वपूर्ण विचार यह है कि RESTful संसाधन मॉडल के लिए मैप करने की आवश्यकता नहीं है। आप एक EnrollmentsController बनाना चाहिए और एक पंक्ति जोड़ें विन्यास के लिए/routes.rb:

map.resources :enrollments 

तो फिर तुम बना सकते हैं और इसलिए तरह अपने रिश्तों को नष्ट कर सकते हैं:

class EnrollmentsController < ApplicationController 
    def create 
     @student = Student.find(params[:student_id]) 
     @course = Course.find(params[:course_id]) 
     @student.courses << @course 
     if @student.save 
     #do happy path stuff 
     else 
     #show errors 
     end 
    end 

    def destroy 
     @student = Student.find(params[:student_id]) 
     @course = @student.courses.find(params[:course_id]) 
     @student.courses.delete(@course) 
    end 
end 

और आप की तरह उन कार्यों के लिए बटन बना सकते हैं इसलिए:

<%= button_to "Enroll", enrollments_path(:student_id => current_student.id, :course_id => @course.id), :method => :post %> 
<%= button_to "Withdraw", enrollment_path(1, :student_id => current_student.id, :course_id => @course.id), :method => :delete %> 

एक प्लेसहोल्डर जहां :enrollment_id जाना और वाक्यात्मक vineg का एक छोटा सा है चाहिए के रूप में कार्य करता है इसके बाद के संस्करण लाइन पर 1 आपको याद दिलाने के लिए कि आप रेल ढांचे की इच्छा को कम कर रहे हैं।

+0

धन्यवाद, यह दो मामूली परिवर्तनों के साथ वास्तव में अच्छा काम करता है: 1. कॉलिंग @ student.courses.destroy (पैराम्स [: कोर्स_आईडी]) ने मुझे एक ActiveRecord :: AssociationTypeMismatch दिया क्योंकि यह कोर्स की तलाश में था और एक स्ट्रिंग मिला। मैंने इसे सही पाठ्यक्रम (@ student.courses.find (पैराम्स [: course_id]) ढूंढकर पहले तय किया) और फिर इसे हटा दिया। 2. मैं कोर्स को नष्ट नहीं करना चाहता हूं, बस एसोसिएशन को हटा दें, इसलिए मैंने –

+0

को नष्ट करने के बजाए एक डिलीट कॉल का उपयोग किया। मैंने आपके परिवर्तनों को दर्शाने के लिए अपना उदाहरण अपडेट कर लिया है। – austinfromboston

0

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

दो और विकल्प:

आप बाकी राज्य सूचना कम बेमानी बना सकता है, या तो वर्ग या छात्र संबंध ही अनुमति से, लेकिन वह अपनी आवश्यकताओं फिट नहीं हो सकता है।

आप दोनों पक्षों पर रिश्ते की जानकारी भी रख सकते हैं, लेकिन निर्णय लें कि कोई कैननिकल है। इसलिए, उदाहरण के लिए, यदि छात्र होने के नाते कक्षा के स्वामित्व में है, तो छात्र नहीं, तो छात्र के संबंधित_to में कोई भी परिवर्तन अनदेखा कर दिया जाता है।

मैं पहला विकल्प पसंद करता हूं, लेकिन मुझे लगता है कि इन्हें कम से कम माना जाना चाहिए।

0

मुझे यकीन नहीं है कि आप दोनों को वास्तव में करना चाहते हैं। आप दोनों के बीच एक कैस्केड डिलीट रिलेशनशिप बनाकर शायद अधिक लाभ प्राप्त करेंगे।

यहां Cascade Deleting on Rails पर एक SO चर्चा है।

0

आपके पास दो नेस्टेड संसाधन हो सकते हैं?

इस पर निर्भर करता है कि आपके पास params[:class_id] है (कृपया यह न कहें कि आपने अपना मॉडल क्लास कहा है!) या कि क्या आप एक params[:student_id] आप बता सकते हैं जो वस्तु के रूप में जो करने के लिए आपरेशन पर बुलाया जा रहा है था (एक तरफ संलग्न निर्माण नमूना देखें):

class SchoolClassController < ApplicationController 

before_filter :get_school_class, :except => [:new, :create, :index] 
before_filter :get_student 

def create 
    get_school_class(false) 
    get_student(false) 
    if @school_class 
    if @student 
     (@school_class.students << @student) 
    else 
     redirect_to "/" and return 
    end 
    else 
    @school_class = SchoolClass.new(params[:school_class]) 
    end 
    if @school_class.save 
    redirect_loc = @student ? student_school_class_path(@student, @school_class) : school_class_path(@student) 
    redirect_to redirect_loc and return 
    else 
    redirect_to "/" 
    end 

end 

private 

def get_school_class(will_redirect=true) 
    begin 
    @school_class = SchoolClass.find(params[:id]) 
    rescue AR::RNF 
    (redirect_to "/" and return false) if will_redirect 
    end 
end 

def get_student(will_redirect=true) 
    if params[:student_id] 
    begin 
     @student = Student.find(params[:student_id]) 
    rescue AR:RNF 
     (redirect_to "/" and return false) if will_redirect 
    end 
    end 
end 

end 

कीजिए किसी भी त्रुटि! वास्तव में एक सैद्धांतिक उदाहरण

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