資料來(lái)源:Rails Guide
Guide
-回調(diào)和 ActiveRecord 生命周期
-認(rèn)識(shí)回調(diào)方法以及如何使用它們
-在特殊的類中封裝回調(diào)行為
1. Definition
Callback 是掛在 AR 對(duì)象生命周期上的一個(gè)個(gè)小鉤子茬斧。當(dāng)你的 Rails 程序中的每個(gè)對(duì)象被創(chuàng)建徐鹤,更新锦援,刪除闯第,甚至從數(shù)據(jù)庫(kù)載入時(shí)都會(huì)驚動(dòng)這一個(gè)個(gè)小鉤子锚沸。你可以通過控制這些小鉤子處理你想要處理的業(yè)務(wù)邏輯队他,但要提醒一下在鉤子中的邏輯不宜太復(fù)雜急灭,若確實(shí)有大量不可以免的操作辽旋,應(yīng)該寫一個(gè)單獨(dú)的類用來(lái)處理這部分邏輯。
2. Types of Callbacks
2.1. Callbacks when create/update
-before_validation
-after_validation
-before_save
-around_save
-before_create/before_update
-around_create/around_update
-after_create/after_update
-after_save
-after_commit/after_rollback
2.2 Callbacks when destroy
-before_destroy
-around_destroy
-after_destroy
-after_commit/after_rollback
2.3 after_initialize
after_initialize
當(dāng)模型對(duì)象被創(chuàng)建或是從數(shù)據(jù)庫(kù)導(dǎo)入并初始化對(duì)象時(shí)調(diào)用杂拨。
Tips: 使用它可以避免你直接修改 AR 的initialize
方法专普。
2.4 after_find
after_find
當(dāng)模型對(duì)象從數(shù)據(jù)庫(kù)獲取記錄,并初始化為對(duì)象時(shí)調(diào)用弹沽。
Tips: after_find
在after_initialize
之前被調(diào)用檀夹。
2.5 after_touch
after_touch
該回調(diào)發(fā)生在一個(gè)模型對(duì)象記錄被觸摸時(shí)。
觸摸表示更新 updated_at
字段贷币,使用touch
方法可以手動(dòng)完成記錄的觸摸击胜。
3. Running and Skipping Callbacks
-(1) 產(chǎn)生回調(diào):
create, update, update_attribute, update_attributes, destroy, destroy_all,
save, save(validate: false), valid?, increment!, decrement!, toggle!
after_find:
all, first, find, find_by, find_by_sql, last
-(2) 跳過回調(diào):
touch, toggle, increment, decrement, increment_counter, decrement_counter,
update_counters, update_column, update_columns, update_all, delete, delete_all
4. Halting Execution
你所添加的回調(diào)函數(shù)會(huì)自動(dòng)排成一個(gè)隊(duì)列等待被執(zhí)行,這個(gè)隊(duì)列包括開頭的驗(yàn)證役纹,之后的回調(diào)偶摔,以及最后的數(shù)據(jù)庫(kù)操作指令。該隊(duì)列被包裹在一層事務(wù)中促脉,如果任何一個(gè)回調(diào)函數(shù)出錯(cuò) (throw(:abort)
或拋出異常辰斋,注意這里不包括返回false
),該鏈條的執(zhí)行終止瘸味,并且向前回滾到最初的狀態(tài)宫仗。
Tips: after_commit/after_rollback
發(fā)生在數(shù)據(jù)庫(kù)操作之后,所以這里出錯(cuò)將會(huì)被無(wú)視
5. Conditional Callbacks
使用:if, :unless
來(lái)增加條件判斷回調(diào)是否要執(zhí)行.
6. Callback Classes
創(chuàng)建類來(lái)封裝回調(diào)方法從而增加代碼的可讀性
7. Transaction Callbacks
after_commit
/after_rollback
是在數(shù)據(jù)庫(kù)操作完成之后才被觸發(fā)的旁仿。他們最佳的適用場(chǎng)景是在與別的外部系統(tǒng)交互時(shí)藕夫,操作無(wú)法成為數(shù)據(jù)庫(kù)事務(wù)的一部分的時(shí)候。
如果你想完成刪除數(shù)據(jù)庫(kù)中的數(shù)據(jù)并且刪除硬盤上的相關(guān)文件操作時(shí)枯冈,
最好使用 after_commit :delete_file_from_disk, on: :destroy
而不是 after_destroy :delete_file_from_disk
after_create_commit
等于 after_commit ... on: :create
after_update_commit
等于 after_commit ... on: :update
after_destroy_commit
等于 after_commit ... on: :destroy
相關(guān)零碎知識(shí)點(diǎn):
- 可以在一個(gè) callback 中定義多個(gè)方法毅贮,方法排列的次序就是方法執(zhí)行的次序。
e.g. before_save :first, :second, :third # 執(zhí)行順序 :first, :second, :third
- 每當(dāng)
create
/update
時(shí)尘奏,屬性的改變都會(huì)存在attr_changed? == true
創(chuàng)建一條新的記錄滩褥,在回調(diào)中attr_changed
=true,attr_was
=nil炫加,attr
=當(dāng)前值瑰煎;
更新一條記錄,在回調(diào)中attr_changed
=true俗孝,attr_was
=之前的值酒甸,attr
=當(dāng)前值.
Note:attr_changed?
為true 是發(fā)生在你改變了這個(gè)記錄的值卻沒有存入數(shù)據(jù)庫(kù)的時(shí)候,另外創(chuàng)建記錄時(shí)只要和默認(rèn)值不一致都會(huì)返回 true赋铝。