ActiveRecord का उपयोग करना, क्या after_update के दौरान रिकॉर्ड के पुराने मान प्राप्त करने का एक तरीका है


81

एक साधारण उदाहरण का उपयोग करके सेटअप करें: मुझे 1 तालिका ( Totals) मिली है amountजो प्रत्येक तालिका के स्तंभ का योग दूसरी तालिका ( Things) में रखती है ।

जब thing.amountअपडेट हो जाता है, तो मैं बस पुराने मूल्य और नए मूल्य के बीच का अंतर जोड़ना चाहूंगा total.sum

अभी मैं घटाकर कर रहा हूँ self.amountके दौरान before_updateऔर जोड़ने self.amountके दौरान after_update। यह सफल होने में बहुत अधिक भरोसेमंद है।

बाधा: मैं सभी लेन-देन का योग बस नहीं करना चाहता।

प्रश्न: काफी सरल, मैं एक after_updateकॉलबैक के दौरान मूल मूल्य का उपयोग करना चाहूंगा । आप ऐसा करने के लिए किस तरीके से आए हैं?

अपडेट: मैं ल्यूक फ्रेंकल के विचार के साथ जा रहा हूं। after_updateकॉलबैक के दौरान आपके पास अभी भी उन self.attr_wasमूल्यों तक पहुंच है जो वास्तव में मैं चाहता था। मैंने एक after_updateकार्यान्वयन के साथ जाने का भी फैसला किया क्योंकि मैं इस तरह के तर्क को मॉडल में रखना चाहता हूं। इस तरह, चाहे मैं भविष्य में लेन-देन को अपडेट करने का फैसला क्यों न करूं, मुझे पता होगा कि मैं लेन-देन के योग को सही ढंग से अपडेट कर रहा हूं। आपके कार्यान्वयन सुझावों के लिए सभी को धन्यवाद।

जवाबों:


149

Ditto हर कोई लेन-देन के बारे में क्या कह रहा है।

ने कहा कि...

रेल 2.1 के रूप में ActiveRecord किसी ऑब्जेक्ट के विशेषता मानों पर नज़र रखता है। इसलिए यदि आपके पास एक विशेषता है total, तो आपके पास एक total_changed?विधि और एक total_wasविधि होगी जो पुराने मूल्य को लौटाती है।

अब इस पर नज़र रखने के लिए अपने मॉडल में कुछ भी जोड़ने की आवश्यकता नहीं है।

अपडेट: यहां ActiveModel के लिए प्रलेखन :: अनुरोध के अनुसार गंदा है


मुझे लगा कि ऐसा कुछ मौजूद है। क्या आप attr_changed के बारे में प्रासंगिक दस्तावेज़ से लिंक कर सकते हैं? और attr_was?
गाबे होलोम्बे

ज़रूर, मैंने जवाब के लिए एक लिंक जोड़ा।
ल्यूक फ्रेंकल

10

कुछ अन्य लोग एक लेनदेन में यह सब लपेटने का उल्लेख कर रहे हैं, लेकिन मुझे लगता है कि यह आपके लिए किया गया है; आपको बस after_ * कॉलबैक में त्रुटियों के लिए अपवाद बढ़ाकर रोलबैक को ट्रिगर करना होगा।

Http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html देखें

एक लेनदेन के भीतर एक बचाओ, बचाओ! या कॉल रन को नष्ट करने की पूरी कॉलबैक श्रृंखला। जिसमें after_ * हुक शामिल हैं। यदि सबकुछ ठीक हो जाता है तो एक कमिट को एक बार चेन पूरा होने के बाद निष्पादित किया जाता है।

यदि पहले से एक कॉलबैक क्रिया को रद्द करता है तो एक रोलबैक जारी किया जाता है। आप किसी भी कॉलबैक में अपवाद को बढ़ाने के लिए एक ROLLBACK ट्रिगर कर सकते हैं, जिसमें after_ * हुक शामिल हैं। ध्यान दें, हालांकि, उस मामले में ग्राहक को इसके बारे में पता होना चाहिए क्योंकि एक साधारण बचत चुपचाप झूठे लौटने के बजाय इस तरह के अपवाद को बढ़ाएगी।



8

अपने पुराने और नए मूल्यों के साथ क्रमशः सभी बदले हुए क्षेत्र प्राप्त करने के लिए:

person = Person.create!(:name => 'Bill')
person.name = 'Bob'
person.save
person.changes        # => {"name" => ["Bill", "Bob"]}

5
मेरा मानना है कि अंतिम पंक्ति अब पढ़ना चाहिए person.previous_changesबजायperson.changes
जेसन Axelson

5

ActiveRecord :: गंदा एक मॉड्यूल है जो विशेषता परिवर्तनों को ट्रैक करने के लिए ActiveRecord में बनाया गया है। तो आप thing.amount_wasपुराने मूल्य प्राप्त करने के लिए उपयोग कर सकते हैं ।


3

इसे अपने मॉडल में जोड़ें:

def amount=(new_value)
    @old_amount = read_attribute(:amount)
    write_attribute(:amount,new_value)
end

फिर अपने after_update कोड में @old_amount का उपयोग करें।


0

सबसे पहले, आपको यह सुनिश्चित करने के लिए एक लेनदेन में होना चाहिए कि आपका डेटा एक साथ लिखा जाए।

अपने प्रश्न का उत्तर देने के लिए, आप पहले_अपेडेट में पुराने मान के लिए एक सदस्य चर सेट कर सकते हैं, जिसे आप उसके बाद after_update में एक्सेस कर सकते हैं, हालांकि यह बहुत ही सुरुचिपूर्ण समाधान नहीं है।


मैं यह देखने के लिए संघर्ष कर रहा हूं कि मैं कैसे लेन-देन का उपयोग करना चाहता हूं। क्या इस तरह का लेनदेन मॉडल में या नियंत्रक में रहता है? क्या मैं अपने 'after_update' और 'before_update' कॉलबैक निकालता हूँ? अंत में, मैं अंतर को निर्धारित करने के लिए पुराने मूल्य को कैसे प्राप्त कर सकता हूं जिसकी मुझे आवश्यकता है?
हाबिल

कोई बात नहीं, मैं देखता हूं कि मुझे कोड को नियंत्रक में रखना होगा। अच्छे थे।
हाबिल

0

आइडिया 1: डेटाबेस ट्रांजेक्शन में अपडेट को लपेटें, ताकि यदि अपडेट विफल हो जाए तो आपकी टोटल टेबल बदली न जाए: ActiveRecord ट्रांसफ़र डॉक्स

आइडिया 2: पहले वाले_अपडेट के दौरान @old_total में पुराने मूल्य को दबाएं।


0

यदि आप अपडेट के बाद किसी विशेष फ़ील्ड का मान प्राप्त करना चाहते हैं, तो आप field_before_last_save पद्धति का उपयोग कर सकते हैं।

Example:

u = User.last
u.update(name: "abc")

u.name_before_last_save will give you old value (before update value)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.