سؤال

أقوم بإعداد رد اتصال 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top