最初のモデルが有効であるかのテスト
生成したモデルの属性に値を与え、インスタンスが有効であるかをテストする(バリデーションはまだ無い)。
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
end
assertは引数の論理値がtrueであることを確認する。
assert_notはその逆で、falseであることを確認する。
存在性の検証(presence)
name属性とemail属性は必ず存在していなければならない。
そこで、バリデーションを設定して各属性が空白の場合は有効でないようにする。
テスト駆動開発で進めていくので、バリデーションを設定する前に、バリデーションが無ければ失敗するテストを書く。
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
nameとemailにそれぞれ空白を入れる。
バリデーションが無いので@user.valid?はtrueを返し、assert_notに反するため、テストは失敗する。
テストを成功させるために、Userモデルにバリデーションを設定する。
class User < ApplicationRecord
validates :name, presence: true
validates :email, presence: true
end
テストをして、成功することを確認しておく。
長さの制限
nameとemailは長すぎないほうが良い。
長すぎるnameとemailを制限するバリデーションを、テストを書いてから設定する。
test "name should not be too long" do
@user.name = "a" * 51
assert_not @user.valid?
end
test "email should not be too long" do
@user.email = "a" * 244 + "@example.com"
assert_not @user.valid?
end
nameは50文字まで、emailはデータベースの文字列の限界である255文字までとする。
そこでnameに51文字、emailに256文字を入れておく。
class User < ApplicationRecord
validates :name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 }
end
presenceオプションとlengthオプションはそれぞれをキーとする一つのハッシュだが、validatesメソッドの最後の引数なので、{}は無くてもよい。
lengthキーの値はハッシュなので、{}が必要である。
テストをして、成功することを確認しておく。
emailのフォーマットの検証
現在のままではemailにメールアドレス以外を入れても保存できてしまうので、フォーマットを制限する。
バリデーションの前に、有効なメールアドレスを確認するテストと、無効なメールアドレスを確認するテストを書く。
test "email validation should accept valid addresses" do
valid_addresses = %w[user@example.com USER@foo.COM A_US-ER@foo.bar.org
first.last@foo.jp alice+bob@baz.cn]
valid_addresses.each do |valid_address|
@user.email = valid_address
assert @user.valid?, "#{valid_address.inspect} should be valid"
end
end
test "email validation should reject invalid addresses" do
invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
foo@bar_baz.com foo@bar+baz.com]
invalid_addresses.each do |invalid_address|
@user.email = invalid_address
assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
end
end
変数にいくつかの有効なメールアドレスを配列にして代入し、eachメソッドを使ってそれぞれのメールアドレスを@user.emailに代入、assertで有効であることを確認する。
無効なメールアドレスのほうのテストはその逆である。
まだバリデーションが無いので、上のテストは成功し、下のテストは失敗する(無効なアドレスも有効と見なされるから)。
assertの第二引数に文字列を与えると、テストが失敗した際にエラーメッセージとして表示することができる。
inspectメソッドは「オブジェクトを分かりやすい文字列にして返す」メソッドらしいが、イマイチよくわからない。
なお、%w[]を使うと、文字列の配列を簡単に作ることができる。
>> %w[foo bar baz]
=> ["foo", "bar", "baz"]
フォーマットの設定
フォーマットを設定するためには、formatオプションを使う。
validates :email, format: { with: /<regular expression>/ }
/<regular expression>/のところに正しいメールアドレスを表す正規表現(Regurar Expression, regex)を入れる。
正規表現を理解する必要は今のところ無いので、コピペして以下のようにする。
class User < ApplicationRecord
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX }
end
テストをして、成功することを確認しておく。