Validating presence

最基本的驗證功能,就是驗證屬性值有沒有存在(presence),這節將實作讓使用者存進資料庫之前,確保兩個欄位 nameemail 的值都有存在。

先針對 name 寫一個測試,檢查 name 屬性值是否存在。先把 @username 屬性值設為空字串(包含一些空格),然後再使用 assert_not 方法確認這個使用者物件是無效的。

assert_not 方法是確認測試失敗的意思,反之 assert 是確認測試成功。也就是說,先故意寫一個應該要回傳 false 的測試:先故意把 @user.name 設為 blank,但一開始測試失敗是因為 @user.name 為 blank 是沒問題的,因為還沒加上驗證。等到加上驗證之後,再跑一次測試,就會成功。

test/models/user_test.rb

require 'test_helper'

class UserTest < ActiveSupport::TestCase

  def setup
    @user = User.new(name: "Example User", email: "[email protected]")
  end

  test "should be valid" do
    assert @user.valid?
  end

  test "name should be present" do
    @user.name = "     "
    assert_not @user.valid?
  end
end

執行測試,測試確定失敗(Red):

$ bundle exec rake test:models

然後在 app/models/user.rb 加上驗證存在的程式碼,使用 validates 方法,參數為 presence: true,它是一個只有一個元素可以選擇的 Hash,當 Hash 作為參數放在最後面,可以省略 {}

class User < ActiveRecord::Base
  validates :name, presence: true
end

其實 validates 是個方法,所以加入 () 可以寫成:

class User < ActiveRecord::Base
  validates(:name, presence: true)
end

進入到 Rails console,檢查加入驗證之後會出現什麼結果:

$ rails console --sandbox
> user = User.new(name: "", email: "[email protected]")
> user.valid?
=> false

回傳 false 表示驗證失敗,可以使用 errors.full_messages 查看失敗時所產生的 error 物件(錯誤訊息):

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

這段錯誤訊息其實是用 blank? 方法驗證存在性。

當驗證失敗,如果要嘗試儲存到資料庫裡,會失敗:

> user.save
=> false

最後執行測試,因為已經加入驗證,所以會成功(Green):

$ bundle exec rake test:models

現在就可以繼續加上 email 的驗證測試了:

test/models/user_test.rb

.
.
test "email should be present" do
  @user.email = "     "
  assert_not @user.valid?
end

在 User model 加入 email 的驗證功能:

app/models/user.rb

validates :email, presence: true

執行測試,顯示成功(Green):

$ bundle exec rake test