Tbpgr Blog

元エンジニア 人事 tbpgr(てぃーびー) のブログ

Ruby on Rails | ActiveRecord | Callback

概要

ActiveRecord | Callback

詳細

Active Recordはそのライクサイクルに様々なフックが用意されています。
Callback はクラスマクロ形式で設定する。例えば

class User < ActiveRecord::Base
  validates :login, :email, presence: true

  before_validation :some_hook

  protected
    def some_hook
      logger.info "some_hook"
    end
end

とすれば、 validationの直前に「some_hook」というログが出力されます

サンプル

save, create, update, destroy のフックの呼び出しを確認します。

テーブル定義
CREATE TABLE "articles" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
  "title" varchar(255), 
  "text" text, 
  "created_at" datetime, 
  "updated_at" datetime
);
動作確認用モデル
class Article < ActiveRecord::Base
  has_many :comments, dependent: :destroy

  HOOKS = %i{
    before_validation
    after_validation
    before_save
    before_create
    around_create
    after_create
    before_update
    around_update
    after_update
    after_save
    before_destroy
    around_destroy
    after_destroy
  }
  HOOKS.each { |h|send(h, h) }

  protected

  HOOKS.each do |sym|
    define_method sym do
      logger.info sym
    end
  end
end
試行 その1 save

rails console(pry)で試行します。

[1] pry(main)> a = Article.new
=> #<Article id: nil, title: nil, text: nil, created_at: nil, updated_at: nil>
[2] pry(main)> a.title = 'save'
=> "save"
[3] pry(main)> a.save
   (0.1ms)  begin transaction
:before_validation
:after_validation
:before_save
:before_create
:around_create
:after_create
:after_save
   (0.1ms)  commit transaction
=> true
試行 その2 create

rails console(pry)で試行します。

[1] pry(main)> a = Article.create(title: 'some title103', text: 'some text')
   (0.1ms)  begin transaction
:before_validation
:after_validation
:before_save
:before_create
:around_create
:after_create
:after_save
   (0.1ms)  commit transaction
=> #<Article id: nil, title: "some title103", text: "some text", created_at: "2014-07-03 23:10:53", updated_at: "2014-07-03 23:10:53">
試行 その3 update

rails console(pry)で試行します。

[1] pry(main)> a = Article.find 1
  Article Load (0.6ms)  SELECT  "articles".* FROM "articles"  WHERE "articles"."id" = 1 LIMIT 1
=> #<Article id: 1, title: "some title1", text: "some Text1", created_at: "2014-06-27 22:56:03", updated_at: "2014-06-27 23:39:55">
[2] pry(main)> a.update(title: 'changed title')
   (0.2ms)  begin transaction
:before_validation
:after_validation
:before_save
:before_update
:around_update
:after_update
:after_save
   (0.2ms)  commit transaction
=> true
試行 その4 destroy

rails console(pry)で試行します。

[1] pry(main)> a26 = Article.find_by id:26
  Article Load (1.1ms)  SELECT  "articles".* FROM "articles"  WHERE "articles"."id" = 26 LIMIT 1
=> #<Article id: 26, title: "some title101", text: "some text", created_at: "2014-07-03 23:59:45", updated_at: "2014-07-03 23:59:45">
[2] pry(main)> a26.destroy
   (0.1ms)  begin transaction
  Comment Load (1.6ms)  SELECT "comments".* FROM "comments"  WHERE "comments"."article_id" = ?  [["article_id", 26]]
:before_destroy
:around_destroy
:after_destroy
   (0.1ms)  rollback transact