मॉडल से विशेषता परिवर्तनों का पता कैसे लगाएं?


85

मैं रेल में एक कॉलबैक फ़ंक्शन बनाना चाहता हूं जो एक मॉडल को सहेजने के बाद निष्पादित करता है।

मेरे पास यह मॉडल है, क्लेम जिसका एक विशेषता 'स्टेटस' है जो दावे की स्थिति के आधार पर बदलता है, संभव मान लंबित, समर्थन, अनुमोदित, अस्वीकृत हैं

डेटाबेस में 'लंबित' के डिफ़ॉल्ट मान के साथ 'स्थिति' है।

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

मेरा विचार मॉडल में एक समारोह है:

    after_save :check_state

    def check_state
      # if status changed from nil to pending (created)
      do this

      # if status changed from pending to approved
      performthistask
     end

मेरा सवाल यह है कि मैं मॉडल के भीतर बदलाव से पहले पिछले मूल्य की जांच कैसे करूं?

जवाबों:


173

आपको ActiveModel :: गंदे मॉड्यूल को देखना चाहिए : आपको अपने दावा मॉडल पर निम्नलिखित कार्य करने में सक्षम होना चाहिए:

claim.status_changed?  # returns true if 'status' attribute has changed
claim.status_was       # returns the previous value of 'status' attribute
claim.status_change    # => ['old value', 'new value'] returns the old and 
                       # new value for 'status' attribute

claim.name = 'Bob'
claim.changed # => ["name"]
claim.changes # => {"name" => ["Bill", "Bob"]}

ओह! रेल की खुशियाँ!


6
यह मॉडल के सहेजने के बाद काम नहीं करेगा जो उसने पूछा है।
टॉम रॉसी

4
@TomRossi, dirtyकॉल में काम करता है after_save(दोनों रेल में 2.3 और 3.x)। मैंने कई बार इसका इस्तेमाल किया है।
हरीश शेट्टी

11
@ टॉमीसी, गंदे झंडों को कमिट करने के बाद रीसेट कर दिया जाता है, इसलिए वे after_commitरेल 3.00 टी में पेश किए गए कॉलबैक में उपलब्ध नहीं होंगे । वे निश्चित रूप से में काम करेंगे after_save
हरीश शेट्टी

मुझे पता नहीं था! मैंने सोचा था कि एक बार सहेजने के बाद वे फिर से सेट हो जाएंगे!
टॉम रॉसी

5
@TomRossi मैंने कुछ साल पहले इसी धारणा के साथ शुरू किया था। जब मैंने after_save में गंदे झंडे को जांचने की कोशिश की तो यह काम कर गया। संक्षेप में, के after_saveबीच एक राज्य के लिए एक कॉलबैक है after DMLऔर before_commit। आप after_saveअपवाद को फेंककर पूरे लेनदेन को समाप्त कर सकते हैं। यदि आप वर्तमान ऑपरेशन को प्रभावित करने से बचाने के बाद कुछ करना चाहते हैं, तो after_commit:-)
हरीश शेट्टी

38

आप इसका उपयोग कर सकते हैं

self.changed

यह इस रिकॉर्ड में बदले गए सभी स्तंभों की एक सरणी लौटाता है

आप भी उपयोग कर सकते हैं

self.changes

जो स्तंभों का एक हैश लौटाता है और जो पहले और बाद में परिणाम के रूप में परिवर्तित होता है


7
बस यह कहने के लिए कि यह कहना अनावश्यक है कि self.इन पर उपयोग करना अनावश्यक है - आप बस कह सकते हैं changedऔर changes
user664833

@ user664833 और अधिक विशेष रूप से, आप selfमॉडल में खुद को छोड़ सकते हैं , लेकिन आप किसी भी ऑब्जेक्ट पर object.changedऔर के साथ इन पर कॉल कर सकते हैं object.changes। :)
जोशुआ पिंटर

4

मेरा सुझाव है कि आपके पास उपलब्ध राज्य मशीन प्लगइन्स में से एक पर एक नज़र है:

दोनों में से कोई एक आपको राज्यों और राज्यों के बीच संक्रमण स्थापित करने देगा। अपनी आवश्यकताओं को संभालने का बहुत उपयोगी और आसान तरीका।


मैं रूबीम-ऐस्म को एक कोशिश दे रहा हूं। मान लें कि मेरे पास क्लास क्लेम है "लंबित" का। यदि मैं स्थिति फ़ील्ड (ताकि यह 'लंबित' चलेगा) में भरने के बिना एक क्लेम कर रहा था, तो क्या AASM 'enter_pending' विधि चलाएगा?
डेविड सी

2

रेल 5.1+ के लिए, आपको सक्रिय रिकॉर्ड विशेषता विधि का उपयोग करना चाहिए: save_change_to_attribute?

saved_change_to_attribute? (attr_name, ** विकल्प) `

क्या हमने पिछली बार सहेजे जाने पर इस विशेषता को बदल दिया था? इस विधि को saved_change_to_name?इसके स्थान पर लागू किया जा सकता है saved_change_to_attribute?("name")। के समान व्यवहार करता है attribute_changed?। कॉलबैक के बाद यह विधि उपयोगी है यह निर्धारित करने के लिए कि कॉल को सहेजने के लिए एक निश्चित विशेषता बदल गई है।

विकल्प

from जब पास किया जाता है, तो यह विधि गलत वापस आ जाएगी जब तक कि मूल मूल्य दिए गए विकल्प के बराबर न हो

to जब पास किया जाता है, तो यह विधि गलत हो जाएगी जब तक कि मूल्य को दिए गए मूल्य में नहीं बदला जाता

तो आपका मॉडल इस तरह दिखेगा, यदि आप विशेषता मान में परिवर्तन के आधार पर कुछ विधि को कॉल करना चाहते हैं:

class Claim < ApplicationRecord
  
  after_save :do_this, if: Proc.new { saved_change_to_status?(from: nil, to: 'pending') }

  after_save :do_that, if: Proc.new { saved_change_to_status?(from: 'pending', to: 'approved') }

  
  def do_this
    ..
    ..
  end

  def do_that
    ..
    ..
  end

end

और यदि आप कॉलबैक में मूल्य परिवर्तन की जांच नहीं करना चाहते हैं, तो आप निम्न कार्य कर सकते हैं ::

class Claim < ApplicationRecord

  after_save: :do_this, if: saved_change_to_status?


  def do_this
    ..
    ..
  end

end

0

मैंने कई स्थानों पर सवाल उठते देखा है, इसलिए मैंने इसके लिए एक छोटा-सा बकवास पत्र लिखा, जिससे कोड को थोड़ा अच्छा बनाया जा सके (और एक लाख से बचने के लिए / हर जगह बयान): https://github.com/ronna-s / on_change । मुझे आशा है कि वह मदद करेंगे।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.