Railsで属性が変更された場合にのみコールバックを実行する


94

アプリに次の関連付けがあります。

# Page 
belongs_to :status

私は、コールバックいつでも実行したいstatus_idpage変更されましたが。

ですから、page.status_id4から5になったら、それをキャッチできるようにしたいと思います。

その方法は?

回答:


198

Rails 5.1以降

class Page < ActiveRecord::Base
  before_save :do_something, if: :will_save_change_to_status_id?

  private

  def do_something
    # ...
  end
end

ActiveRecord :: Dirtyを変更したコミットはこちらです:https : //github.com/rails/rails/commit/16ae3db5a5c6a08383b974ae6c96faac5b4a3c81

これらの変更に関するブログ投稿は次のとおりです。https//www.ombulabs.com/blog/rails/upgrades/active-record-5-1-api-changes.html

Rails 5.1以降でのActiveRecord :: Dirtyの変更について私が自分で作成した概要は次のとおりです。

ActiveRecord :: Dirty

https://api.rubyonrails.org/classes/ActiveRecord/AttributeMethods/Dirty.html

保存する前に(オプションの変更)

オブジェクトを変更した後、データベースに保存する前、またはbefore_saveフィルター内:

  • changes 今なら changes_to_save
  • changed? 今なら has_changes_to_save?
  • changed 今なら changed_attribute_names_to_save
  • <attribute>_change 今なら <attribute>_change_to_be_saved
  • <attribute>_changed? 今なら will_save_change_to_<attribute>?
  • <attribute>_was 今なら <attribute>_in_database

保存後(重大な変更)

オブジェクトの変更後、データベースへの保存後、またはafter_saveフィルター内:

  • saved_changes(に代わるprevious_changes
  • saved_changes?
  • saved_change_to_<attribute>
  • saved_change_to_<attribute>?
  • <attribute>_before_last_save

レール<= 5.0

class Page < ActiveRecord::Base
  before_save :do_something, if: :status_id_changed?

  private

  def do_something
    # ...
  end
end

これは、before_saveコールバックがメソッド呼び出しの戻り値に基づいて条件付きで実行できるという事実を利用しています。このstatus_id_changed?メソッドはActiveModel :: Dirtyから取得されます。これにより_changed?、属性名に追加するだけで、特定の属性が変更されたかどうかを確認できます。

do_somethingメソッドをいつ呼び出すかは、あなたのニーズ次第です。定義されたActiveRecord :: Callbacksのいずれか、before_saveまたはそのafter_save両方である可能性があります。


4
このソリューションは新しいバージョンでは非推奨です。
マテウスルイス

6
Rails 5.1以降の情報で更新されました。
pdobb


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.