rails 使用after_commit 來(lái)替代 after_save
首先得明白after_save
和after_commit
的區(qū)別
1、after_save
將回調(diào)函數(shù)包含在同一個(gè)事務(wù)中疏尿,那么要么全部成功窗宦,要么全部失敗结蟋∧ぃ回調(diào)函數(shù)中的拋出的異常會(huì)導(dǎo)致整個(gè)操作失敗似舵。
2做修、after_commit
是在事務(wù)提交之后霍狰,再進(jìn)行的處理,那么即使回調(diào)函數(shù)拋出異常饰及,也不會(huì)導(dǎo)致之前的操作失敗蔗坯。
舉個(gè)例子。
class ZZDeal
attr_accessor :title
after_save: record_to_redis
def record_to_redis
# TODO
rails Exception
end
end
# console
zz = ZZDeal.last
1] pry(main)> zz = ZZDeal.first
D, [2014-09-18T19:38:13.416572 #10908] DEBUG -- : ZZDeal Load (1.4ms) SELECT `zz_deals`.* FROM `zz_deals` ORDER BY `zz_deals`.`id` ASC LIMIT 1
=> #<ZZDeal id: 1, title: 'my_first_name'>
zz.title = "jjjj"
zz.save
D, [2014-09-18T19:38:22.943780 #10908] DEBUG -- : (0.5ms) BEGIN
D, [2014-09-18T19:38:22.989825 #10908] DEBUG -- : SQL (1.0ms) UPDATE `zz_deals` SET `title` = 'jjjj', `updated_at` = '2014-09-18 19:38:22' WHERE `zz_deals`.`id` = 1
D, [2014-09-18T19:38:22.990678 #10908] DEBUG -- : (0.5ms) ROLLBACK
[5] pry(main)> zz.reload.title
D, [2014-09-18T19:38:37.321616 #10908] DEBUG -- : ZZDeal Load (1.6ms) SELECT `zz_deals`.* FROM `zz_deals` WHERE `zz_deals`.`id` = 1 LIMIT 1
=> "my_first_name"
發(fā)現(xiàn)燎含,title并沒(méi)有改變宾濒。
若我將 after_save
變更為 after_commit
,便是另一種效果
class ZZDeal
attr_accessor :title
after_commit: record_to_redis, :on => [:create, :update]
def record_to_redis
# TODO
rails Exception
end
end
zz = ZZDeal.last
1] pry(main)> zz = ZZDeal.first
D, [2014-09-18T19:38:13.416572 #10908] DEBUG -- : ZZDeal Load (1.4ms) SELECT `zz_deals`.* FROM `zz_deals` ORDER BY `zz_deals`.`id` ASC LIMIT 1
=> #<ZZDeal id: 1, title: 'my_first_name'>
zz.title = "wahaha"
[4] pry(main)> zz.save
D, [2014-09-18T19:40:29.632423 #10926] DEBUG -- : (0.7ms) BEGIN
D, [2014-09-18T19:40:29.687067 #10926] DEBUG -- : SQL (0.8ms) UPDATE `zz_deals` SET `title` = 'wahaha', `updated_at` = '2014-09-18 19:40:29' WHERE `zz_deals`.`id` = 1
D, [2014-09-18T19:40:29.824718 #10926] DEBUG -- : (0.6ms) COMMIT
D, [2014-09-18T19:40:29.825749 #10926] DEBUG -- : (0.5ms) ROLLBACK
[6] pry(main)> zz.reload.title
D, [2014-09-18T19:40:39.389478 #10926] DEBUG -- : ZZDeal Load (8.4ms) SELECT `zz_deals`.* FROM `zz_deals` WHERE `zz_deals`.`id` = 1 LIMIT 1
=> "wahaha"
數(shù)據(jù)庫(kù)先進(jìn)行了COMMIT再進(jìn)行了ROLLBACK,那么之前的數(shù)據(jù)肯定是保存成功了屏箍。
所以兩種情況分別對(duì)待绘梦,如果你確實(shí)是需要同時(shí)成功,同時(shí)失敗赴魁,那么after_save 是不錯(cuò)的選擇卸奉,但是,如果不希望回調(diào)函數(shù)影響數(shù)據(jù)的保存颖御,那么你需要after_commit榄棵。
另外,在after_save中潘拱,會(huì)出現(xiàn)臟數(shù)據(jù)的情況疹鳄。
宣傳語(yǔ)
歷經(jīng)兩個(gè)半月的準(zhǔn)備,三次大改版芦岂,十七次小改版瘪弓。le1024終于要和大家見(jiàn)面了。
le1024每天推薦1~3段盔腔,有趣杠茬、有愛(ài)月褥、有故事的視頻弛随。
為您工作、學(xué)習(xí)宁赤、生活之余增加一點(diǎn)快樂(lè)的感覺(jué)舀透。程序員必看的快樂(lè)視頻網(wǎng)站