iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
Modern Web

Ruby on Rails面試題挑戰系列 第 18

Ruby on Rails面試題挑戰 Day18 - before_save 與 after_save 使用時機有何不同?

  • 分享至 

  • xImage
  •  

When would you use a before_save vs. after_save callback?
before_save 與 after_save 使用時機有何不同?


昨天簡介了callback這個有點容易混淆的名詞,簡單複習一下callback的概念,callback是在物件生命週期的特定時機執行某些程式碼,例如在物件創造前(before_create)、存取後(after_save),刪掉之後(after_destroy)等等。

## Create an object
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
after_commit/after_rollback

## Updating an Object
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit/after_rollback

如果需要在存取之後更新一個物件會需要額外的資料庫執行,所以如果需要更新物件的屬性(attribute),使用before_save會是比較有效率的選擇,另外官方也提到盡量避免去在callback中去更新屬性,可能會導致非預期的副作用(?),取而代之的是使用before_create或是更之前的callback。

但有時物件的資訊要等到save之後才存在(譬如說id),如果需要這個id來產生某些關聯性的data,那可能就需要使用after_save callback。

另外在搜尋資料的過程也發現,關於after_save,需要更小心的使用,其實在after_save的時候資料還未被實在的寫入資料庫。以下模擬一個物件存取的過程。

def save(*args)
  ActiveRecord::Base.transaction do
    self.before_validation
    self.validate!
    self.after_validation
    self.before_save
    db_connection.update(self, *args)
    self.after_save
  end
  self.after_commit
end

這告訴我們關於after_save的兩件事

  1. transaction還未結束,Model其實還沒有真的儲存
  2. 任何在transaction內發生的錯誤都會倒回所有的存取

在某些情況下,這樣的特性可能有問題

class Shipment < ApplicationRecord
  after_save :notify_client, if: proc { saved_change_to_status? }
  
  def notify_client
    Email::Service.send_status_update_email(id)
  end
end

在上面這段程式中,如果after_save 的方法出錯的話,整個存取動作會被倒回,如果不想要有這種特性的話,最好是使用after_commit來取代。

你可以這樣回答:

如果需要在存取之後更新一個物件會需要額外的資料庫執行,所以如果需要更新物件的屬性(attribute),使用before_save會是比較有效率的選擇。

但有時物件的資訊要等到save之後才存在(譬如說id),如果需要這個id來產生某些關聯性的data,那可能就需要使用after_save callback。

參考資料

1.Rubyguide-ActiveRecord Callbacks

2.53 Ruby on Rails Interview Questions and Answers

3.How to Safely Use ActiveRecord’s after_save


上一篇
Ruby on Rails面試題挑戰 Day17 - 什麼是Callback?
下一篇
Ruby on Rails面試題挑戰 Day19 - delete與destroy差異在哪?
系列文
Ruby on Rails面試題挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言