提升Model操作安全性的技巧


Posted by Nacho on 2020-11-01

2020/10/29
紀錄一下最近同事、老闆codereview時提出的一些改進建議!

exception raising => 使用save!

當要將 ActiveRecord 物件存到DB時加上 ! 來捕獲例外事件,如果有使用Rollbar,這樣產生的例外事件可以被 rollbar 紀錄。
save! 會去執行 ActiveRecord 的 validation,如果驗證失敗則拋出 RecordInvalid 的錯誤;save 用在紀錄尚未建立或更新現有的紀錄,但不建議以save做資料更新,避免語意不明造成的後續的維護問題!

user.save!
# or
if user.save
else
end

exception raising 的做法也適用於 create!, update!, destroy!, first_or_create! and find_or_create_by!

避免這種三元運算子

把三元運算子用在清楚的邏輯。負責的邏輯用 if else 處理。

# bad => 用 if else 展開
self.deleted_at ? self.update!(deleted_at: nil) : self.update!(deleted_at: Time.current)

優先採用 Rails 提供的方法

我曾在Model自己寫了一個 find_or_update 的方法,目的是在table有紀錄的情況下更新該筆紀錄,或找不到便新增紀錄,但因為長得很像find_or_create_by,同事review說到這蠻容易誤會的!所以如果 Rails 提供方法已經能 cover 一些你要做的事,請優先採用它!

# bad
def self.find_or_update(args)
  feeling = Feeling.find_by(
                     user_id: args[:user_id])
  if feeling.nil?
    return Feeling.create!(
                     author_id: args[:author_id],
                     user_id: args[:user_id],
                     scale: args[:scale])
  end
  return feeling.update!(
                  author_id: args[:author_id], 
                  scale: args[:scale])
end

# good
def self.create_or_update_by!(args)
  feeling = self.find_or_create_by!(
                   author_id: args[:author_id],
                   user_id: args[:user_id],
                   scale: args[:scale])
  feeling.update!(
            author_id: args[:author_id], 
            scale: args[:scale])
  feeling
end

#Model #Rails #Codereview #ActiveRecord







Related Posts

[TensorFlow Certification Day4] TensorFlow的人工智能, 機器學習和深度學習簡介 Week4

[TensorFlow Certification Day4] TensorFlow的人工智能, 機器學習和深度學習簡介 Week4

CSS保健室|animation

CSS保健室|animation

我很菜,所以只會用原生 JS 跟 CSS 寫「口罩地圖 」Ep.05

我很菜,所以只會用原生 JS 跟 CSS 寫「口罩地圖 」Ep.05


Comments