モデルのpublished属性がfalseからtrueに変更された場合にのみ通知を送信するように、モデルオブザーバーでafter_saveコールバックを設定しています。 changed?などのメソッドは、モデルが保存される前にのみ有用であるため、私が現在(および失敗)しようとしている方法は次のとおりです。
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
フィルターでは、can_changed?
アクセサーを使用します(少なくともRails 3で、Railsについては不明です) 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
コールバックで行われた変更を知りたい場合:
model.saved_changes
model.previous_changes
参照: http://api.rubyonrails.org/classes/ActiveModel/Dirty.html#method-i-previous_changes
後でこれを見る人には、現在(2017年8月)Googleを上回っています:この動作はRails 5.2で変更されることに言及する価値があります、および ActiveModel :: Dirty が少し変更されたRails 5.1の時点で非推奨の警告があります。
何を変更しますか?
attribute_changed?
-コールバックでafter_*
メソッドを使用している場合、次のような警告が表示されます。
非推奨の警告:コールバック後の
attribute_changed?
の動作は、Railsの次のバージョンで変更されます。新しい戻り値は、save
が返された後のメソッド呼び出しの動作を反映します(たとえば、現在返されているものの反対)。現在の動作を維持するには、代わりにsaved_change_to_attribute?
を使用します。 (/PATH_TO/app/models/user.rb:15のsome_callbackから呼び出されます)
言及されているように、関数をsaved_change_to_attribute?
に置き換えることで簡単に修正できます。したがって、たとえば、name_changed?
はsaved_change_to_name?
になります。
同様に、attribute_change
を使用してbefore-after値を取得している場合、これも同様に変更され、以下をスローします。
非推奨の警告:コールバック後の
attribute_change
の動作は、Railsの次のバージョンで変更されます。新しい戻り値は、save
が返された後のメソッド呼び出しの動作を反映します(たとえば、現在返されているものの反対)。現在の動作を維持するには、代わりにsaved_change_to_attribute
を使用します。 (/PATH_TO/app/models/user.rb:20のsome_callbackから呼び出されます)
繰り返しますが、言及したように、このメソッドは名前をsaved_change_to_attribute
に変更し、["old", "new"]
を返します。または、すべての変更を返すsaved_changes
を使用します。これらはsaved_changes['attribute']
としてアクセスできます。
before_save
の代わりにafter_save
でこれを実行できる場合、これを使用できます。
self.changed
このレコードで変更されたすべての列の配列を返します。
以下も使用できます。
self.changes
変更された列のハッシュを返し、結果の前後に配列として返します
「選択された」答えは私にとってはうまくいきませんでした。 CouchRest :: Model(Active Modelに基づく)でRails 3.1を使用しています。 _changed?
メソッドは、after_update
フックで変更された属性に対してtrueを返さず、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
で、割り当てがfalseを返し、「ハッシュ」が返されない場合に必要です。
もっと簡単な方法があると思う、私はRailsを初めて使う