コールバックの続き
コールバックの実行となるトリガ
データベースに影響を与える処理
と 保存時じゃなくてもトリガとなる valid?
- create
- create!
- destroy
- destroy!
- destroy_all
- save
- save!
- save(validate: false) • toggle!
- touch
- update_attribute
- update
- update!
- valid?
データベースから、レコードを読み込むたびに呼び出される after_find
では、下記がトリガとなる
- all
- first
- find
- find_by
- find_by_*
- find_by_*!
- find_by_sql
- last
関連モデルのコールバック
親子関係のモデル経由でコールバックを実行することができる
class User < ApplicationRecord
has_many :posts , dependent: :destroy
end
class Post < ApplicationRecord
def log_destroy_action
puts 'Userが消えたよ!'
end
end
>> user = User.first
=> #<User id: 1>
>> user.posts.create!
=> #<Post id: 1, user_id: 1>
>> user.destroy
Userが消えたよ!
=> #<User id: 1>
:if や :unlessでオプションをつけられる
バリデーションでよく使う
class User < ApplicationRecord
before_save :user_search, if: :user_exists?
end
コールバックclassを作れる
Active Recordはコールバックメソッドをカプセル化したクラスを作成できる(Railsガイドより引用)
class PictureFileCallbacks
def after_destroy(picture_file)
if File.exist?(picture_file.filepath) File.delete(picture_file.filepath)
File.delete(picture_file.filepath)
end
end
end
クラス内で宣言することにより、コールバックメソッドはモデルオブジェクトをパラメーターとして受け取れるようになる
=> これでモデル内で使用可能
class PictureFile < ApplicationRecord after_destroy PictureFileCallbacks.new
after_destroy PictureFileCallbacks.new
end
コールバックをインスタンスメソッドとして宣言したため、 PictureFileCallbacks オブジェクト
を新しくインスタンス化する必要があった
コールバックをクラスメソッドとして宣言する方がいいパターンも...
class PictureFileCallbacks
def self.after_destroy(picture_file)
if File.exist?(picture_file.filepath) File.delete(picture_file.filepath)
File.delete(picture_file.filepath)
end
end
end
クラスメソッドなら、インスタンス化は不要ですね♪
トランザクションコールバック
データベースのトランザクションが完了したときにトリガされるコールバック
Active Record のモデルから、データベーストランザクションの一部に含まれていない外部のシステムとやりとりを行ないたい場合に使用する
- after_commit
- after_rollback
※ データベースの変更のcommit、rollbackが完了するまでトリガされない