2013-09-23 5 views
6

रेल में लेनदेन ब्लॉक का उपयोग करके, मैं एक शॉट में मॉडल के कई उदाहरण कैसे अपडेट/सहेज सकता हूं?रेल में एक ActiveRecord लेनदेन में एकाधिक रिकॉर्ड अपडेट करें

मैं सैकड़ों अभिलेखों के लिए मूल्यों को अपडेट करना चाहता हूं; मान प्रत्येक रिकॉर्ड के लिए अलग हैं। यह एक विशेषता के लिए एक जन-अद्यतन स्थिति है। Model.update_all (attr: value) यहां उचित नहीं है।

MyModel.transaction do 
    things_to_update.each do |thing| 
     thing.score = rand(100) + rand(100) 
     thing.save 
    end 
end 

save बल्कि आसपास के लेन-देन में अपडेट batching से, अपने आप लेन-देन जारी करने के लिए लगता है। मैं चाहता हूं कि सभी अपडेट एक बड़े लेनदेन में जाएं।

मैं इसे कैसे पूरा कर सकता हूं?

+1

ActiveRecord आयात [मणि] हो सकता है (https://github.com/zdennis/activerecord-import/wiki) होगा आपके लिए काम .. – tihom

उत्तर

0

मुझे यकीन है कि नहीं हूँ, लेकिन शायद आप अनेक लेन-देन कई प्रश्न साथ भ्रमित कर रहे हैं।

आपके द्वारा पोस्ट किया गया कोड एक एकल लेनदेन तैयार करेगा (उदाहरण के लिए यदि कोई अपवाद हुआ तो सभी अपडेट वापस लुढ़क जाएंगे), लेकिन प्रत्येक save परिणामस्वरूप एक अलग अपडेट क्वेरी होगी।

यदि रूबी कोड की बजाय एसक्यूएल का उपयोग करके अद्यतन करना संभव है तो शायद यह जाने का सबसे अच्छा तरीका होगा।

+0

मुझे एक समय में 1000 या उससे अधिक रिकॉर्ड पर अपडेट चलाने होंगे, इसलिए मैं 1000 अलग-अलग अपडेट क्वेरी नहीं चलाऊंगा, क्योंकि यह बहुत धीमी है। क्या आप उन्हें एक शॉट में निष्पादित कर सकते हैं? – Avishai

+0

यदि अद्यतन वास्तव में 'स्कोर' को 2 यादृच्छिक संख्याओं के योग पर सेट करना है (और आपने अभी इसे प्रश्न को सरल बनाने के लिए उदाहरण के रूप में उपयोग नहीं किया है) तो आप' update_all' का उपयोग कर सकते हैं लेकिन पोस्टग्रेस का उपयोग करके मान सेट कर सकते हैं ' निश्चित मानों का उपयोग करने के बजाय यादृच्छिक 'फ़ंक्शन। – mikej

3

आप जानते थे कि आप आईडी 1, 2 के साथ चीजों को सेट करना चाहता था कहो, और 3 64 (बस यादृच्छिक संख्या के विपरीत), तो आप कर सकते थे स्कोर, 2, 8 के लिए, और:

UPDATE 
    things AS t 
SET 
    score = c.score 
FROM 
    (values 
    (1, 2), 
    (2, 30), 
    (4, 50) 
) as c(id, score) 
where c.id = t.id; 

तो रेल के साथ, आप ऊपर दिए गए ब्लॉक को निष्पादित करने के लिए ActiveRecord::Base.connection#execute का उपयोग करेंगे, लेकिन सही मान स्ट्रिंग इंटरपोलेटेड के साथ।

-1

मुझे लगता है कि आपको बस "सेव" करने के लिए "सेव" विधि बदलने की ज़रूरत है। यदि कोई भी अपडेट विफल रहता है, तो विधि सहेजती है! एक अपवाद उत्पन्न करता है। एक सौदे के ब्लॉक के भीतर एक अपवाद होता है, लेन-देन पूरे आपरेशन को उलट देता है (रोलबैक)

MyModel.transaction do 
    things_to_update.each do |thing| 
    thing.score = rand(100) + rand(100) 
    thing.save! 
end 
+0

यह एकाधिक SQL अनुरोध उत्पन्न करेगा। –

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