2009-10-03 13 views
17

मुझे ActiveRecord :: गंदा और संबंधित विधियों के बारे में पता है, लेकिन मुझे ऐसा कोई साधन नहीं दिख रहा है जिसके द्वारा मैं एक विशेषता परिवर्तित घटना की सदस्यता ले सकता हूं। कुछ ऐसा:परिवर्तित ActiveRecord विशेषताओं के लिए कॉलबैक?

class Person < ActiveRecord::Base 
    def attribute_changed(attribute_name, old_value, new_value) 
    end 

    #or 

    attribute_changed do |attribute_name, old_value, new_value| 
    end 
end 

क्या इसके लिए कोई रेल मानक या प्लगइन है? मुझे लगता है कि यह कहीं और होना चाहिए और मैं बस इसे याद कर रहा हूँ।

उत्तर

18

cwninja के जवाब को चाल करना चाहिए, लेकिन इसके लिए थोड़ा और कुछ है।

सबसे पहले, मूल विशेषता हैंडलिंग write_attribute विधि के साथ की जाती है ताकि आपको इसमें टैप करना चाहिए।

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

का उपयोग करते हुए कस्टम कॉलबैक आप इस तरह यह कर सकता है:

class Person < ActiveRecord::Base 

    def write_attribute(attr_name, value) 
    attribute_changed(attr_name, read_attribute(attr_name), value) 
    super 
    end 

    private 

    def attribute_changed(attr, old_val, new_val) 
     logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}" 
    end 

end 

आप रेल कॉलबैक (विशेष रूप से उपयोगी आप एक से अधिक कॉलबैक और/या उपवर्गीकरण हो सकता है अगर) का उपयोग करने के लिए आप कुछ इस तरह कर सकता है की कोशिश करना चाहता है तो :

class Person < ActiveRecord::Base 
    define_callbacks :attribute_changed 

    attribute_changed :notify_of_attribute_change 

    def write_attribute(attr_name, value) 
    returning(super) do 
     @last_changed_attr = attr_name 
     run_callbacks(:attribute_changed) 
    end 
    end 

    private 

    def notify_of_attribute_change 
     attr = @last_changed_attr 
     old_val, new_val = send("#{attr}_change") 
     logger.info "Attribute Changed: #{attr} from #{old_val} to #{new_val}" 
    end 

end 
+0

पीटर, यह सुंदर है, मुझे "write_attribute" का एक टन बचाने के लिए जा रहा है, मैंने अपने पूरे कोड को अलग कर दिया है। धन्यवाद! – BushyMark

+0

लगता है कि यह केवल रेल 2 के लिए है। – lulalala

+0

बिना किसी तारीख के Google के माध्यम से इसका आया। इस हालिया वॉथथ्रू ने मुझे जो चाहिए था: ['after_callbacks'] में मॉडल के परिवर्तनों को कैसे ट्रैक करें (http://ruby-journal.com/how-to-track-changes-with-after-callbacks-in- रेल-3-या-नए /) – Jay

5

कोशिश:

def attribute_changed(attribute_name, old_value, new_value) 
end 

def attribute=(attribute_name, value) 
    returning(super) do 
    attribute_changed(attribute_name, attribute_was(attribute_name), attribute(attribute_name)) 
    end 
end 

अभी इस आविष्कार किया है, लेकिन यह काम करना चाहिए।

+0

मुझे सही पथ नीचे सेट करने के लिए धन्यवाद। – Mario

3

तुम हमेशा निजी विधि changed_attributes पहुँच सकते हैं और वहाँ कुंजी जाँच एक before_save का उपयोग कर और क्या आप करेंगे इसके साथ कर सकता है।

14

रेल 3 के लिए:

class MyModel < ActiveRecord::Base 
    after_update :my_listener, :if => :my_attribute_changed? 

    def my_listener 
    puts "Attribute 'my_attribute' has changed" 
    end 
end 

में टिप्पणी की: https://stackoverflow.com/a/1709956/316700

मैं इस बारे में आधिकारिक दस्तावेज भी नहीं मिलता है।

+2

मेरा मानना ​​है कि जैसे ही सहेजने से पहले, स्मृति में एक विशेषता बदल दी जाती है, यानी 'my_object.some_attr = "foo" कॉलबैक उत्पन्न करने के बाद, उसे एक विधि में शामिल किया जाना चाहिए। – MikeJ

+0

'after_update' को रेल 2.3 के बाद से हटा दिया गया है (http://apidock.com/rails/ActiveRecord/Callbacks/after_update) – schmijos

2

सबसे आसान तरीका है कि मैंने पाया:

after_save :my_method, :if => Proc.new{ self.my_attribute_changed? } 

def my_method 
    ... do stuff... 
end 
+1

after_save: my_method,: if =>: my_attribute_changed? –

+0

अच्छा! यह भी बेहतर है :) – pesta

8

रेल के लिए 4

def attribute=(value) 
    super(value) 
    your_callback(self.attribute) 
end 

क्या आप write_attribute(:attribute, your_callback(self.attribute)) और नहीं attribute= का उपयोग करना चाहिए विशेषता के मान को अधिलेखित करना चाहते हैं या आप अधिक पाश हूँ तो जब तक आप एक ढेर बहुत गहरा अपवाद नहीं मिलता है।

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