यदि विशेषता बदल जाती है तो 3 जांचें


153

यह जांचने की आवश्यकता है कि क्या रेल्स 3 में अपडेट से पहले विशेषताओं का एक ब्लॉक बदल गया है।

सड़क 1, सड़क 2, शहर, राज्य, ज़िपकोड

मुझे पता है कि मैं कुछ ऐसा इस्तेमाल कर सकता हूं

if @user.street1 != params[:user][:street1]
  then do something....
end

लेकिन कोड का वह टुकड़ा वास्तव में लंबा होगा। क्या कोई क्लीनर रास्ता है?

जवाबों:


282

ActiveModel की जाँच करें :: गंदा (डिफ़ॉल्ट रूप से सभी मॉडलों पर उपलब्ध)। प्रलेखन वास्तव में अच्छा है, लेकिन यह आपको इस तरह की चीजें करने देता है:

@user.street1_changed? # => true/false

यदि आप यह देखने की कोशिश कर रहे हैं कि क्या एक विशेषता को एक रूप में बदल दिया गया था (जो ओपी क्या कर रहा है लगता है) यह मदद नहीं करता है।
मार्क फ्रेजर

8
ज़रूर करता है। यदि आप परम हैश का उपयोग करके मान निर्दिष्ट करते हैं, तो ये फॉर्म से आए हैं।
पीटर ब्राउन

क्या होगा अगर मैं ऐसा कुछ करना चाहूंगा: model.collection.changed_size_by? या ऐसा कुछ
मूरो डायस

@ मौरोडियास को आपको संग्रह के गुणों को ट्रैक करने के लिए अपना तर्क लिखना होगा।
पीटर ब्राउन

मैं इसके लिए कुछ परीक्षण परिवाद का उपयोग करने का प्रयास करने वाला हूं। कुछ भी हो सकता है, वैसे भी TY
मौरो डायस

54

यह है कि मैंने कई विशेषताओं में परिवर्तन के लिए जाँच की समस्या को हल किया।

attrs = ["street1", "street2", "city", "state", "zipcode"]

if (@user.changed & attrs).any?
  then do something....
end

changedविधि गुण उस वस्तु के लिए बदल की एक सरणी देता है।

दोनों @user.changedऔर attrsसरणियां हैं इसलिए मैं अंतरच्छेदन ( ary & other aryविधि देखें ) प्राप्त कर सकता हूं । चौराहे का परिणाम एक सरणी है। any?सरणी पर कॉल करके , मैं सच हो जाता हूं अगर कम से कम एक चौराहा हो।

बहुत उपयोगी भी, changed_attributesविधि उनके मूल मूल्यों और के साथ विशेषताओं का एक हैश लौटाती हैchanges एक हैश लौटाती है और अपने मूल और नए मूल्यों (एक सरणी में) के साथ विशेषताओं का एक हैश लौटाती है।

आप एपीडॉक की जांच कर सकते हैं कि किन संस्करणों ने इन विधियों का समर्थन किया है।

http://apidock.com/rails/ActiveModel/Dirty


1
यह करने का एक अच्छा तरीका है। ऐतिहासिक रूप से मैंने ऐसा किया है if attrs.any?{|attr| @user.send("#{attr}_changed?")}जब मैं जांचना चाहता हूं कि क्या कई अलग-अलग विशेषताओं में से एक बदल गया है - निश्चित रूप से, मैं केवल उन एट्रस के साथ ऐसा करता हूं जो मैंने खुद को परिभाषित किया है, क्योंकि मुझे उपयोगकर्ता पैरामीटर को एक sendविधि में फेंकना पसंद नहीं है । ;)
nzifnab

14

ActiveModel::Dirtyमेरे लिए काम नहीं किया क्योंकि @model.update_attributes()परिवर्तन छिपा दिया। तो यह है कि मैं कैसे updateएक नियंत्रक में एक विधि में परिवर्तन का पता चला है :

def update
  @model = Model.find(params[:id])
  detect_changes

  if @model.update_attributes(params[:model])
    do_stuff if attr_changed?
  end
end

private

def detect_changes
  @changed = []
  @changed << :attr if @model.attr != params[:model][:attr]
end

def attr_changed?
  @changed.include :attr
end

यदि आप बहुत सारे विशेषता परिवर्तनों का पता लगाने की कोशिश कर रहे हैं, तो यह गड़बड़ हो सकता है। शायद यह एक नियंत्रक में नहीं करना चाहिए, लेकिन meh।


9
इसके लायक क्या है, आप इसे कर सकते हैं previous_changesजिसके साथ यह डिफ़ॉल्ट रूप से भी उपलब्ध है।
जेसन गेल्यूटेन

2
#update_attributesपरिवर्तनों को छिपा नहीं सकता है। यह रिकॉर्ड बचाता है, इसलिए मॉडल को अपडेट किया जाता है और इसमें कोई बदलाव नहीं होता है। आपको changed?इसे सहेजने से पहले मॉडल में फ़ील्ड को बदलने और जांचने की आवश्यकता है। अर्थात। @ model.field = 'foo' या@model.attributes = @model.attributes.merge(params[:model])
Grzegorz

9

रेल के लिए 5.1+ कॉलबैक

रूबी ऑन रेल्स 5.1 के रूप में, attribute_changed?और attribute_wasActiveRecord विधियों को पदावनत किया जाएगा

के saved_change_to_attribute?बजाय का उपयोग करेंattribute_changed?

@user.saved_change_to_street1? # => true/false

अधिक उदाहरण यहाँ


2

उपरोक्त उत्तर बेहतर हैं, लेकिन फिर भी ज्ञान के लिए हमारे पास एक और दृष्टिकोण है, आइए एक वस्तु (@design) के लिए 'कैटागोरी' कॉलम मान को बदल दें,

@design.changes.has_key?('catagory')

.Changes एक हैश को कॉलम के नाम और मानों के साथ एक सरणी के रूप में लौटाएगा जिसमें प्रत्येक कॉलम के लिए दो मान [old_value, new_value] होते हैं। उदाहरण के लिए ऊपर दिए गए कैटागिरी को 'ABC' से @design के 'XYZ' में बदल दिया जाता है,

@design.changes   # => {} 
@design.catagory = 'XYZ'
@design.changes # => { 'catagory' => ['ABC', 'XYZ'] }

संदर्भ के लिए ROR में परिवर्तन

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