質問

モデルオブザーバーにafth_saveコールバックを設定して、モデルの場合にのみ通知を送信します 公開 属性はfalseからtrueに変更されました。次のような方法です かわった? モデルが保存される前にのみ便利です。現在(そして失敗して)そうしようとしている方法は次のとおりです。

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? アクセサー(少なくとも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 折り返し電話:

Rails 5.1以上

model.saved_changes

レール<5.1

model.previous_changes

参照してください: http://api.rubyonrails.org/classes/activemodel/dirty.html#method-i-previous_changes

現在(2017年8月)がGoogleを上回っているので、これを後で見た人にとっては、この動作が変更されることは言及する価値があります。 Rails 5.2, 、およびRails 5.1の場合の非推奨警告があります。 ActiveModel ::ダーティ 少し変更しました。

何を変えますか?

使用している場合 attribute_changed? の方法 after_*- コールバック、次のような警告が表示されます。

非推奨警告:の動作 attribute_changed? 次のバージョンのRailsでは、After After Callbacksが変更されます。新しい返品値は、後にメソッドを呼び出す動作を反映します 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 次のバージョンのRailsでは、After After Callbacksが変更されます。新しい返品値は、後にメソッドを呼び出す動作を反映します 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

変更された列のハッシュをアレイとして結果として返します。

「選択された」答えは私にとってはうまくいきませんでした。 CouchRest :: Model(アクティブモデルに基づいて)でRails 3.1を使用しています。 _changed? メソッドは、変更された属性の場合はtrueを返しません 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, 、割り当てが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