2010-11-06 11 views
8

मान लीजिए प्रत्येक Projecthas_manyTasksकेवल has_many एसोसिएशन में परिवर्तन सहेजें जब आप मूल ऑब्जेक्ट को सफलतापूर्वक सहेजते हैं?

अगर मैं

some_project.tasks = list_of_tasks 
some_project.save 

परियोजना के कार्यों अपडेट कर दिया है, भले ही बचाने में विफल रहता है है। यदि list_of_tasks में नए रिकॉर्ड शामिल हैं, तो प्रोजेक्ट के कार्यों को हटा दिया गया है यदि सहेजने में विफल रहता है! डब्ल्यूएचओए!

यदि सहेजने में विफल रहता है, तो परियोजना के साथ गड़बड़ करना शुरू करने से पहले परियोजना के समान कार्य होना चाहिए। मैं यह व्यवहार कैसे प्राप्त करूं और यह डिफ़ॉल्ट क्यों नहीं है?

उत्तर

8

एक सौदे में बयान संलग्न करें:

Project.transaction do 
    p.tasks = task_list 
    p.save! 
end 

save! विधि त्रुटि होने पर एक अपवाद है, जो वापस रोल कार्य सूची के लिए किया कोई भी परिवर्तन फेंकता है।

यदि आप विषय पर थोड़ा और गहराई से गोता लगाने के लिए documentation पढ़ सकते हैं तो आप documentation पढ़ सकते हैं।

+0

यह काम करता है, लेकिन इस दृष्टिकोण का अर्थ है कि जब भी मैं अपने पूरे एप्लिकेशन में कार्यों को अपडेट करता हूं तो मुझे इसे लेनदेन में लपेटना याद रखना होगा (और मुझे यकीन है कि मैं भूल जाऊंगा)। अगर मैं डीआरवाई फैशन में 'प्रोजेक्ट' मॉडल में इस व्यवहार को समाहित कर सकता हूं तो यह बेहतर होगा। –

+4

ठीक है, एक विधि 'replace_tasks (new_tasks)' को परिभाषित करें जो कि बस करता है – glebm

0

#save पर कॉल करने से पहले आप पूछ सकते हैं कि some_project#valid? है या नहीं। यदि some_project अमान्य रिकॉर्ड होने के कारण सहेजने में विफल रहता है, तो यह समस्या को हल करने में मदद करता है, लेकिन यह एक व्यापक समाधान नहीं है।

रेल के डिफ़ॉल्ट व्यवहार के लिए, यह समझ में आता है। कह रहा है कि some_project.tasks = list_of_tasks कह रहा है "कुछ मौजूदा कार्यों को कुछ_प्रोजेक्ट से हटाएं और इन नए को असाइन करें"। आप मौजूदा एसोसिएशन ऐरे के संदर्भ को छोड़ रहे हैं और एक नया ब्रांड असाइन कर रहे हैं। यह डीबी में ActiveRecord द्वारा प्रतिबिंबित होता है।

+1

यह काम नहीं करता है। 'some_project.tasks = list_of_tasks' जैसे ही इसे कॉल किया जाता है, मौजूदा कार्य सूची को दूर कर देता है, भले ही मैं 'some_project.save' कहूं या नहीं। मैं वास्तव में विश्वास नहीं कर सकता कि यह डिफ़ॉल्ट व्यवहार है - यह वास्तव में प्रतिद्वंद्वी है! –

+1

"कुछ_project.tasks = list_of_tasks' कह रहा है" कुछ मौजूदा कार्यों को कुछ_प्रोजेक्ट से हटाएं और इन नए लोगों को असाइन करें "। मुझे लगता है कि यह कहने की तरह है कि "कुछ_प्रोजेक्ट' से सभी मौजूदा कार्यों को हटा दें और इन नए लोगों को असाइन करें * जब मैं 'some_project' * को सहेजता हूं।' Some_project.name =" जो भी "मैं सहेजता हूं तब तक प्रभावी नहीं होता है, न ही' some_project.tasks = list_of_tasks' –

+0

@ होरेस लोब: विभिन्न जानवर, विभिन्न नियम। आईआईआरसी, अधिकांश ओआरएम इस तर्क का पालन करते हैं क्योंकि यह आपके अपेक्षित व्यवहार से लागू करने के लिए आसान तरीका है (मेरा विश्वास करो, आप इस के साथ आने वाले पहले व्यक्ति नहीं हैं) क्षमा करें, वास्तव में एक स्रोत नाम नहीं कर सकते हैं। – pkoch

3

मुझे विश्वास है कि accepts_nested_attributes_for() व्यवहार आप चाहते हैं प्रदान करेगा:

class Project < ActiveRecord::Base 
    accepts_nested_attributes_for :tasks 
end 

यह एक सौदे के अंदर सब कुछ लपेटो चाहिए। इसके बाद आपको उस फॉर्म को बनाने की ज़रूरत है जो तदनुसार कार्यों को पॉप्युलेट करे। आपके प्रोजेक्ट मॉडल में tasks_attributes विधि tasks विधि के बजाय कहा जाता है। अधिक जानकारी के लिए the API देखें।

3

आपको लगता है कि AutosaveAssociation सुविधा वह है जो आप चाहते हैं।

class Project < ActiveRecord::Base 
    has_many :tasks, :autosave => true 
end 

यह बचत को स्वचालित रूप से एक लेनदेन में लपेटना चाहिए।

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