はじめに
こんにちは。アメリカにて独学でエンジニアを目指している者です。
現在、Railsチュートリアルを用いて学習を進めていますが、Railsのテストでよく使用される valid?
メソッドについて、「valid」という英単語の意味である「有効な」と単純に解釈していたため、本来の動作を十分に理解していませんでした。
そこで本記事では、valid?
メソッドの基本的な動作とテストでの利用例について解説します。
valid?メソッドの基本動作
Railsのvalid?
メソッドは、モデルに定義された全てのバリデーションを実行し、その結果に基づいてオブジェクトが「有効か無効か」を判断します。
以前は、valid?
が単にオブジェクトの状態(true
or false
)を返すだけだと勘違いしていましたが、実際には以下のようなプロセスで動作しています。
-
バリデーションの実行
モデルで設定したpresence: true、uniqueness: true、format: { with: ... }
など、各種バリデーションが順に評価されます。 -
エラー情報の蓄積
バリデーションに失敗した場合、そのエラー情報がerrors
オブジェクトに追加され、どの属性がどのような理由で無効になったかを明確にします。 -
真偽値の返却
全てのバリデーションが成功すればtrue
、1つでも失敗すればfalse
が返されます。
テストにおけるvalid?の利用例
テストコードでは、valid?
を用いてモデルの状態が期待通りになっているかどうかを検証します。
以下に、モデル側のコード例とテストケースのコード例を併記して説明します。
モデル側のコード例
例えば、Userモデルでは name
と email
に対して、必須性と一意性のバリデーションを設定します。
class User < ApplicationRecord
validates :name, presence: true, uniqueness: true
validates :email, presence: true, uniqueness: true
end
テストケースのコード例
次に、メールアドレスの一意性を検証するテストケースの例です。
test 'email addresses should be unique' do
duplicate_user = @user.dup
@user.save
assert_not duplicate_user.valid?
end
テストの流れ
-
@user.dup
でオブジェクトを複製
オリジナルのユーザーオブジェクト@user
の属性を引き継いだ新しいオブジェクトduplicate_user
を作成します。 -
元のユーザーを保存
@user.save
により、元のユーザーがデータベースに登録されます。この時点で、メールアドレスの一意性がデータベース上で確認できる状態になります。 -
バリデーションの実行
duplicate_user.valid?
が呼ばれると、uniqueness: true
のバリデーションが実行され、データベースに問い合わせが発行されます。
既に同じ名前とメールアドレスが存在するため、duplicate_user
は無効と判断されます。
このように、valid?
はメモリ上のオブジェクトに対してバリデーションを実行しますが、一部のバリデーション(例:uniqueness
)はデータベースの状態を反映するため、実際にDBへの問い合わせが発生する仕組みになっています。
まとめ
Railsの valid?
メソッドは、単にオブジェクトの状態を返すだけでなく、その場でバリデーションを実行し、エラー情報を収集しながらオブジェクトの有効性を判断します。
特に、uniqueness: true
のようにデータベースの状態に依存するバリデーションが含まれている場合、valid?
は実際にデータベースへクエリを発行して確認を行います。
もしコードの意味がすぐに理解できない場合は、自分の先入観にとらわれず、1つ1つのコードの意味や動作を考察することが、エンジニアとして成長するための大切なプロセスだと感じました。