iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 22
0
Modern Web

Ruby礦工的Rails地圖系列 第 22

淺談callback -- 物件生命週期的掛鉤

其實想寫這個題目想很久
也是因為沒有特別心得所以不斷跳過
但今天在找題目的過程中,
忽然覺得,時候到了!!(其實是沒找到什麼好寫的主題)
所以決定今天介紹

回呼就是在rails物件新增、修改、驗證、刪除的生命週期中
可以觸發的事件方法
一般有兩種寫法:

class Event < ActiveRecord::Base
  #方法一
  before_create do
    # ... 略
  end

  #方法二
  before_validation :setup_defaults
  protected
  def setup_defaults
      #...略
  end
end

如果邏輯比較短,可以考慮使用方法一
兩者效果是相同的

回呼可以綁定特定的動作,例如:

after_validation :set_location, on: [ :create, :update ]

如此就只有create, update會生效

依照動作先後的不同,回呼是內建執行順序的
不會因為程式碼的位置而有不同
這點要特別注意
比方說:

class User < ActiveRecord::Base
  after_initialize do |user|
    puts "You have initialized an object!"
  end
 
  after_find do |user|
    puts "You have found an object!"
  end
end

>> User.first
You have found an object!
You have initialized an object!
=> #<User id: 1>

User物件會先被找到(after_find),
接著才會被初始化(after_initialize)
這樣的先後關係不會因為程式碼撰寫時的位置不同而更動
所以要了解物件生命週期的先後關係

就像驗證可以略過一樣,
回呼一樣也可以略過,但要特別注意
有些重要的動作常常藉由回呼來實作
所以略過回呼可能會產生企業邏輯上的錯誤
不可不慎

下面的用法會略過回呼:

  • decrement
  • decrement_counter
  • delete
  • delete_all
  • increment
  • increment_counter
  • toggle
  • update_column
  • update_columns
  • update_all
  • update_counters

實務上在專案中最常用到的應該是after_create
在建立物件完成後,將相關的物件一併產生
例如:產生一個客戶的網站
將初始的設定檔與預設頁面一起生成

回呼可以用ifunless來設定條件,例如

class Order < ActiveRecord::Base
  before_save :normalize_card_number, if: :paid_with_card?
end

:paid_with_card?回傳true的時候,回呼才會執行

要特別注意的是
整個物件的生命週期會被一個交易所覆蓋
如果before_方法傳回錯誤
那after_方法就不會接著執行,而是會rollback回滾

換句話說,要小心before方法如果不小心回傳false
整個交易就會終止,而且不容易除錯
如果不確定的話就回傳true吧

今天就到這邊囉~


上一篇
路由 routes (2)
下一篇
避免重複render錯誤
系列文
Ruby礦工的Rails地圖30

尚未有邦友留言

立即登入留言