LoginSignup
0
0

More than 3 years have passed since last update.

【Rails】Userモデルの基本的なバリデーションとテスト【Rails Tutorial 6章まとめ】

Posted at

最初のモデルが有効であるかのテスト

生成したモデルの属性に値を与え、インスタンスが有効であるかをテストする(バリデーションはまだ無い)。

test/models/user_test.rb
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/models/user_test.rb

  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モデルにバリデーションを設定する。

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
  validates :email, presence: true
end

テストをして、成功することを確認しておく。

長さの制限

nameとemailは長すぎないほうが良い。
長すぎるnameとemailを制限するバリデーションを、テストを書いてから設定する。

test/models/user_test.rb
  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文字を入れておく。

app/models/user.rb
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/models/user_test.rb
  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)を入れる。
正規表現を理解する必要は今のところ無いので、コピペして以下のようにする。

app/models/user.rb
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

テストをして、成功することを確認しておく。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0