存在性を検証する
最も基本的なバリデーションは「存在性(Presence)」です。
これは単に、渡された属性が存在することを検証します。
例えばこの節では、ユーザーがデータベースに保存される前にnameとemailフィールドの両方が存在することを保証します。
ここではこの要求を新しいユーザーを作るためのユーザー登録フォームにまで徹底させる方法を確認
します。
まずはname属性の存在性に関するテストを追加
します。
具体的にはリスト 6.7のように、まず@user変数のname属性に対して空白の文字列をセット
します。
そして、assert_notメソッドを使って Userオブジェクトが有効でなくなったこと
を確認します。
name属性にバリデーションに対するテスト
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
end
test "should be valid" do
assert @user.valid?
# Userオブジェクトの有効性を調べる。
end
test "name should be present" do
@user.name = " "
assert_not @user.valid?
end
end
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 24064
FAIL["test_name_should_be_present", #<Minitest::Reporters::Suite:0x000055b2fa9fc588 @name="UserTest">, 0.036220663999984026]
test_name_should_be_present#UserTest (0.04s)
Expected true to be nil or false
test/models/user_test.rb:14:in `block in <class:UserTest>'
2/2: [==============================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.04021s
2 tests, 2 assertions, 1 failures, 0 errors, 0 skips
name属性の存在を検査する方法
は、リスト 6.9に示したとおり、
validates メソッドにpresence: true
という引数を与えて使うことです。
presence: trueという引数は、要素が1つのオプションハッシュ
です。
メソッドの最後の引数としてハッシュを渡す場合、波カッコを付けなくても問題ありません。
name属性の存在性を検証する
class User < ApplicationRecord
validates :name, presence: true
end
validates
は単なるメソッドです。カッコを使ってリスト 6.9を同等のコードに書き換えたものを次に示します。
class User < ApplicationRecord
validates(:name, presence: true)
end
カッコが省略できる。
>> user = User.new(name: "", email: "michael@example.com")
(0.1ms) begin transaction
=> #<User id: nil, name: "", email: "michael@example.com", created_at: nil, updated_at: nil>
>> user.valid?
=> false
user変数が有効
かどうかをvalid?メソッドでチェックすることができます。
もしオブジェクトが1つ以上の検証に失敗したときは、falseを返します。
また、すべてのバリデーションに通ったときにtrueを返します。
今回の場合、検証が1つしかないので、どの検証が失敗したかわかります。
しかし、失敗したときに作られるerrorsオブジェクトを使って確認
すれば、便利。
>> user.errors.full_messages
=> ["Name can't be blank"]
>> user.save
=> false
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 32299
2/2: [==============================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.04125s
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
email属性の存在性についてもテストを書いてみましょう。
最初は失敗しますが、コードを追加することで成功する
email属性の検証に対するテスト
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
@user = User.new(name: "Example User", email: "user@example.com")
end
test "should be valid" do
assert @user.valid?
end
test "name should be present" do
@user.name = ""
assert_not @user.valid?
end
test "email should be present" do
@user.email = " "
assert_not @user.valid?
end
end
email属性の存在性を検証する
class User < ApplicationRecord
validates :name, presence: true
validates :email, presence: true
end
ubuntu:~/environment/sample_app (modeling-users) $ rails t
Running via Spring preloader in process 6088
Started with run options --seed 7475
11/11: [============================] 100% Time: 00:00:01, Time: 00:00:01
Finished in 1.93017s
11 tests, 22 assertions, 0 failures, 0 errors, 0 skips
演習
1.新しいユーザーuを作成し、作成した時点では有効ではない(invalid)ことを確認してください。
なぜ有効ではないのでしょうか? エラーメッセージを確認してみましょう。
2.u.errors.messagesを実行すると、ハッシュ形式でエラーが取得できることを確認してください。
emailに関するエラー情報だけを取得したい場合、どうやって取得すれば良いでしょうか?
>> u = User.new(name: "", email: "")
(0.1ms) begin transaction
=> #<User id: nil, name: "", email: "", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> []
# どう言う意味? 両方空という意味なのかな。
>> u.email = "abc@def.com"
=> "abc@def.com"
>> u.save
=> false
>> u.save
=> false
>> u
=> #<User id: nil, name: "", email: "abc@def.com", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> ["Name can't be blank"]
# 名前が空
>> u.email = ""
=> ""
>> u
=> #<User id: nil, name: "", email: "", created_at: nil, updated_at: nil>
>> u.name = "abc"
=> "abc"
>> u
=> #<User id: nil, name: "abc", email: "", created_at: nil, updated_at: nil>
>> u.errors.full_messages
=> ["Name can't be blank"]
>> u.save
=> false
# 保存されていないはずなのに
# ↓はなんで結果が変わるの?
>> u.errors.full_messages
=> ["Email can't be blank"]
# emailが空