ユーザーを検証する
作成したUserモデルに、アクセス可能なnameとemail属性が与えられました。
しかし、これらの属性はどんな値でも
取ることができてしまいます。現在は(空文字を含む)あらゆる文字列が有効
です。
名前とメールアドレスには、もう少し何らかの制限
があってよいはずです。
例えばnameは空であってはならず、emailはメールアドレスのフォーマットに従う必要があります。
さらに、メールアドレスをユーザーがログインするときの一意のユーザー名として使おうとしているので、メールアドレスがデータベース内で重複することのないようにする
必要もあります。
要するに、nameとemailにあらゆる文字列を許すのは避ける
べき。
これらの属性値には、何らかの制約を与える必要があります。
Active Record では検証(Validation)という機能を通して、こういった制約を課すことができるようになっています。
ここでは、よく使われるケースのうちのいくつかについて説明します。
それらは存在性(presence)の検証、長さ(length)の検証、フォーマット(format)の検証、一意性(uniqueness)の検証です。
よく使われる最終検証として確認(confirmation)を追加
します。ユーザーが制約に違反したときに、検証機能によって自動的に表示される有用なエラーメッセージ
をお見せします。
有効性を検証する
モデルのバリデーション機能
は、テスト駆動開発とまさにピッタシの機能と言えます。
バリデーション機能は強力ですが、うまく動いている自信を持つのが難しい
です。
しかし、(テスト駆動開発のように)まず失敗する
テストを書き、次にテストを成功させるよう
に実装すると、期待した通りに動いている自信を持てるようになります。
具体的なテスト方法について、まず有効なモデルのオブジェクトを作成
し、その属性のうちの1つを有効でない属性に意図的に変更
します。そして、バリデーションで失敗するかどうかをテストする、といった方針で進めていきます。
念のため、最初に作成時の状態に対してもテストを書いておき、最初のモデルが有効であるかどうか
も確認しておきます。
コマンドを実行してUser用テストの原型ができているはずなので、まずはその中身から見ていきましょう
デフォルトのUserテスト(モックのみ)
require 'test_helper'
class UserTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
有効なオブジェクトに対してテストを書くために、setup
という特殊なメソッドを使って有効なUserオブジェクト(@user)を作成します(このメソッドは第3章の演習でも少し取り上げました)。
setupメソッド内に書かれた処理は、各テストが走る直前に実行されます。
@userはインスタンス変数ですが、setup
メソッド内で宣言しておけば、すべてのテスト内でこのインスタンス変数が使えるようになります。
したがって、valid?
メソッドを使ってUserオブジェクトの有効性をテストすることができます。作成したコードをリスト 6.5に示します。
有効なUserかどうかをテストする
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メソッドを使ってテストします。@user.valid?がtrueを返すと成功し、falseを返すと失敗します。
ubuntu:~/environment/sample_app (modeling-users) $ rails test:models
Started with run options --seed 24042
1/1: [==============================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.03134s
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
rails test:modelsというコマンドを実行していますが、これはモデルに関するテストだけ
を走らせるコマンドです。
演習
1.コンソールから、新しく生成したuserオブジェクトが有効(valid)であることを確認してみましょう。
>> user
=> #<User id: nil, name: "Example User", email: "user@example.com", created_at: nil, updated_at: nil>
>> user.valid?
=> true
2.6.1.3で生成したuserオブジェクトも有効であるかどうか、確認してみましょう。
>> user2 = User.new(name: "Michael Hartl", email: "michael@example.com")
=> #<User id: nil, name: "Michael Hartl", email: "michael@example.com", created_at: nil, updated_at: nil>
>> user2.valid?
=> true