iT邦幫忙

2022 iThome 鐵人賽

DAY 29
0
Modern Web

Ruby新手村的礦工日記系列 第 29

[ Day 29 ] Rails : 進資料庫先過資料驗證 (Validation) 這關!

  • 分享至 

  • xImage
  •  

當資料寫進資料庫時,需要確保存進來的資料是有效的,你應該不會想要資料庫被塞一些奇怪的資料進來吧!舉例來說,使用者需填入有效的 Email 格式,這就是需要資料驗證的地方。

驗證要在哪做?

資料驗證要寫在哪呢?比較常見的選項有:

  • 前端驗證
  • 後端驗證
  • 資料庫驗證

前端驗證簡單且容易做,但有人關掉 JavaScript ,或是直接檢視 HTML 原始碼,並做一樣的表單,一樣可以寫進資料庫,所以這個不推薦。
資料庫驗證一樣可以做驗證,但是每一個資料庫系統所提供的功能不一定一樣,所以當你換一個資料庫可能會沒辦法正常運行。
後端驗證在 Rails 中 MVC 架構,M 跟 C 可以來做這件事,但是在 Controller 驗證,會使其看起來較為複雜,我們盡量保持 Controller 輕巧短小;所以資料驗證寫在 Model 層是較為合理的且單純的。

補充:
在學習 Rails 的過程中常聽到 "Skinny Controller, Fat Model" 一詞;在開發網站的過程中,常常被告誡商業邏輯要寫在 Model 中而不是 Controller ,這樣的做法會讓商業邏輯更好測試且可以被重複利用,Controller 就做好 View 與 Model 資料交換的角色就好了。

去 Model 加驗證吧!

下面介紹一些常用的驗證!

presence

現在我們有 Owner 的 Model 裡面有 name 欄位,我想要這個欄位是必填資訊,所以我們可以這樣寫:

# owner.rb
class Owner < ApplicationRecord
  validates :name , presence: true
end
# 另一種寫法
class Owner < ApplicationRecord
  validates_presence_of :name
end

這樣我們就完成驗證的條件了,我們到 rails console 建立一個 Owner4 物件:

>> owner4 = Owner.new
=> #<Owner id: nil, name: nil, tel: nil, created_at: nil, updated_at: nil>

我們先看他有沒有什麼錯誤:

owner4.errors.any?
=> false

那我們將它存進資料庫吧!

>> owner4.save
=> false

存入失敗,我們再看有什麼問題:

>> owner4.errors.any?
=> true

>> owner4.errors.full_messages
=> ["Name can't be blank"]

因為有驗證的原因,所以當我 name 欄位沒寫東西,它就不讓我存進資料庫。

uniqueness

當不希望資料庫有一模一樣的名字,我們可以用 uniqueness 來驗證資料庫是否有相同的資料

# owner.rb
class Owner < ApplicationRecord
  validates :name , uniqueness: true
end

在學驗證時,常常會以爲只有用 savecreate 寫入資料庫時才會有驗證錯誤的問題發生,但其實不用寫入資料庫也可以知道這筆資料是否有效。
我們先看目前資料庫有哪些資料:

>> Owner.all
 => #<ActiveRecord::Relation [#<Owner id: 1, name: "春春", tel: nil, created_at: "2022-10-13 06:02:43.505023000 +0000", updated_at: "2022-10-13 06:02:43.505023000 +0000">, #<Owner id: 2, name: "阿肥", tel: nil, created_at: "2022-10-13 06:02:48.212935000 +0000", updated_at: "2022-10-13 06:02:48.212935000 +0000">, #<Owner id: 3, name: "酷酷", tel: nil, created_at: "2022-10-14 06:05:38.616165000 +0000", updated_at: "2022-10-14 06:10:34.652542000 +0000">]>

這邊可以看到第一筆資料有 name: "春春" ,那我們故意新增一筆同名的資料:

owner4 = Owner4.new(name: "春春")

看一下有沒有問題:

>> owner4.errors.any?
=> false

沒有問題,接著我們看可不可以通過驗證:

>> owner4.valids?
=> false

沒通過驗證,為什麼?!看一下錯誤訊息:

>> owner4.errors.full_messages
=> ["Name has already been taken"]

這邊有兩個觀念:

  1. 即使沒有用 save 也是會觸發驗證。
  2. 因為寫了同名的資料,所以他不讓我存入資料庫。

以上介紹兩種基本的兩種驗證方式,更多驗證模式可以去 Rails Guides 查看。

參考資料:

  1. 為自己學 Ruby on Rails
  2. Rails Guides
  3. Rails: skinny controller, skinny model
  4. Ruby on Rails面試題挑戰 Day23 - Fat models, Skinny controllers和 Skinny controllers, Skinny models的意思為何?

上一篇
[ Day 28 ] Rails : Model 的關聯性(多對多)
下一篇
[ Day 30 ] Ruby on Rails 之旅才剛啟航呢!
系列文
Ruby新手村的礦工日記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言