تحديد ما هي السمات التي تم تغييرها في Rails After_save رد الاتصال؟
-
27-09-2019 - |
سؤال
أقوم بإعداد رد اتصال After_save في مراقب النموذج الخاص بي لإرسال إشعار فقط إذا كان النموذج نشرت تم تغيير السمة من خطأ إلى حقيقي. منذ طرق مثل تغير؟ هي مفيدة فقط قبل حفظ النموذج ، والطريقة التي أحاول بها حاليًا (دون جدوى) القيام بذلك هي على النحو التالي:
def before_save(blog)
@og_published = blog.published?
end
def after_save(blog)
if @og_published == false and blog.published? == true
Notification.send(...)
end
end
هل لدى أي شخص أي اقتراحات بشأن أفضل طريقة للتعامل مع هذا ، ويفضل استخدام عمليات الاسترداد للمراقب النموذجية (حتى لا تلوث رمز وحدة التحكم)؟
المحلول
في الخاص بك after_update
تصفية على النموذج لك يستطيع استعمال _changed?
ملحق (على الأقل في القضبان 3 ، غير متأكد من القضبان 2). على سبيل المثال:
class SomeModel < ActiveRecord::Base
after_update :send_notification_after_change
def send_notification_after_change
Notification.send(...) if (self.published_changed? && self.published == true)
end
end
إنه يعمل فقط.
نصائح أخرى
بالنسبة لأولئك الذين يريدون معرفة التغييرات التي تم إجراؤها للتو في after_save
أتصل مرة أخرى:
القضبان 5.1 وأكبر
model.saved_changes
القضبان <5.1
model.previous_changes
انظر أيضا: http://api.rubyonrails.org/classes/activemodel/dirty.html#method-i-previous_changes
لأي شخص يرى هذا لاحقًا ، كما يتصدر حاليًا (أغسطس 2017) Google: تجدر الإشارة إلى أنه سيتم تغيير هذا السلوك القضبان 5.2, ولديه تحذيرات إهمال اعتبارًا من القضبان 5.1 ActiveModel :: القذرة تغير قليلا.
ماذا أغير؟
إذا كنت تستخدم attribute_changed?
الطريقة في after_*
-لقيمة ، سترى تحذيرًا مثل:
تحذير الإهمال: سلوك
attribute_changed?
في الداخل سوف تتغير عمليات الاسترجاعات في الإصدار التالي من القضبان. ستعكس قيمة الإرجاع الجديدة سلوك استدعاء الطريقة بعدsave
عاد (على سبيل المثال عكس ما تعود الآن). للحفاظ على السلوك الحالي ، استخدمsaved_change_to_attribute?
في حين أن. (دعا من Some_Callback AT/Path_to/app/models/user.rb:15)
كما يذكر ، يمكنك إصلاح هذا بسهولة عن طريق استبدال الوظيفة بـ saved_change_to_attribute?
. على سبيل المثال ، name_changed?
يصبح saved_change_to_name?
.
وبالمثل ، إذا كنت تستخدم attribute_change
للحصول على القيم السابقة ، يتغير هذا أيضًا ويرمي ما يلي:
تحذير الإهمال: سلوك
attribute_change
في الداخل سوف تتغير عمليات الاسترجاعات في الإصدار التالي من القضبان. ستعكس قيمة الإرجاع الجديدة سلوك استدعاء الطريقة بعدsave
عاد (على سبيل المثال عكس ما تعود الآن). للحفاظ على السلوك الحالي ، استخدمsaved_change_to_attribute
في حين أن. (يسمى من Some_Callback AT/Path_to/app/models/user.rb:20)
مرة أخرى ، كما يذكر ، تتغير الطريقة إلى الاسم saved_change_to_attribute
الذي يعود ["old", "new"]
. او استعمل saved_changes
, الذي يعيد جميع التغييرات ، ويمكن الوصول إليها على أنها saved_changes['attribute']
.
في حال يمكنك القيام بذلك على before_save
بدلاً من after_save
, ، ستتمكن من استخدام هذا:
self.changed
يعيد مجموعة من جميع الأعمدة التي تم تغييرها في هذا السجل.
تستطيع ايضا استخذام:
self.changes
الذي يعيد تجزئة الأعمدة التي تغيرت وقبل وبعد النتائج كصفائف
لم تنجح إجابة "المختارة" بالنسبة لي. أنا أستخدم Rails 3.1 مع CouchRest :: Model (استنادًا إلى النموذج النشط). ال _changed?
الأساليب لا تعود صحيحًا للسمات المتغيرة في after_update
ربط ، فقط في before_update
صنارة صيد. تمكنت من الحصول عليها للعمل باستخدام (جديد؟) around_update
صنارة صيد:
class SomeModel < ActiveRecord::Base
around_update :send_notification_after_change
def send_notification_after_change
should_send_it = self.published_changed? && self.published == true
yield
Notification.send(...) if should_send_it
end
end
يمكنك إضافة شرط إلى after_update
مثل ذلك:
class SomeModel < ActiveRecord::Base
after_update :send_notification, if: :published_changed?
...
end
ليست هناك حاجة لإضافة شرط داخل send_notification
الطريقة نفسها.
أنا أستخدم هذا لاستخراج علامة تجزئة مع قيم السمات الجديدة ، وهو أمر مفيد بالنسبة لي لتحديث النماذج الأخرى
attributes_changed = self.changes.inject(Hash.new){|hash,attr| ((hash[attr[0].to_sym] = attr[1].last) || attr[1].last == false) && hash}
ال
attr[1].last == false
مطلوب عندما تكون القيمة الجديدة false
, ، حيث تعود المهمة الخاطئة ولم يتم إرجاع "التجزئة".
أعتقد أن هناك طريقة أسهل ، أنا جديد على القضبان
يمكنك فقط إضافة ملحق يحدد ما تقوم بتغييره
class Post < AR::Base
attr_reader :what_changed
before_filter :what_changed?
def what_changed?
@what_changed = changes || []
end
after_filter :action_on_changes
def action_on_changes
@what_changed.each do |change|
p change
end
end
end