2
1

More than 3 years have passed since last update.

ActiveRecordのhook(after_create / after_create_commit)とtransaction

Posted at

気になったこと

ActiveRecordのhookはかなり便利で、レコードのCRUDに合わせてさまざまな処理を入れることができます。
hookした処理内でエラーが発生した時のレコード操作はrollbackされるのかちょっと気になったので確認しました。

結論

after_create
=> hook内でエラーが発生した時にはレコード操作がrollbackされる

after_create_commit
=> hook内でエラーが発生してもレコード操作はcommitされている(それはそうですよね)

前提

ActiveRecordをテストするので何もないテーブルを作成。

create_table :tests do |t|
  t.string :hoge
end

after_create

class Test < ActiveRecord::Base
  after_create :raise_error

  def raise_error
    raise 'after create error'
  end
end
Test.create!

after_createでraiseしつつレコードを作成してみます

実行結果

[1] pry(main)> class Test < ActiveRecord::Base
[1] pry(main)*   after_create :raise_error
[1] pry(main)*
[1] pry(main)*   def raise_error
[1] pry(main)*     raise 'after create error'
[1] pry(main)*   end
[1] pry(main)* end
:raise_error
[2] pry(main)> Test.create!
   (7.9ms)  SET NAMES utf8mb4 COLLATE utf8mb4_bin,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.6ms)  BEGIN
  Test Create (0.7ms)  INSERT INTO `tests` VALUES ()
   (2.0ms)  ROLLBACK
RuntimeError: after create error
from (pry):5:in `raise_error'

transaction内でROLLBACKが発生しているのがわかります。

after_create_commit

class Test < ActiveRecord::Base
  after_create_commit :raise_error

  def raise_error
    raise 'after create commit error'
  end
end
Test.create!

実行ログ

[1] pry(main)> class Test < ActiveRecord::Base
[1] pry(main)*   after_create_commit :raise_error
[1] pry(main)*
[1] pry(main)*   def raise_error
[1] pry(main)*     raise 'after create commit error'
[1] pry(main)*   end
[1] pry(main)* end
:raise_error
[2] pry(main)> Test.create!
   (17.7ms)  SET NAMES utf8mb4 COLLATE utf8mb4_bin,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
   (0.8ms)  BEGIN
  Test Create (0.4ms)  INSERT INTO `tests` VALUES ()
   (2.9ms)  COMMIT
RuntimeError: after create commit error
from (pry):5:in `raise_error'

SQLのCOMMITが入った後にエラーがraiseされているのがわかります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1