ユーザー登録時のバリデーションを追加(1)
scaffoldで自動生成したUserモデルを確認すると分かる通り、まだ何も処理が記述されていません。実際にユーザー登録をする際には以下の要件が必要となるでしょう。
- 名前(name)とメールアドレス(email)が必須
- name、emailの文字数制限
- emailの形式チェック
- emialは大文字・小文字を区別しない
これら値のチェック機構をバリデーションと呼びます。Railsではモデルが継承するActiveRecordの機能としてバリデーション用のDSL(Domain Specific Language)が用意されています。これらを利用してバリデーションを実装していきます。
presenceバリデーションの追加
name、emailはユーザー登録時に空で登録することはできない、ということをバリデーションで表現するには、
validates [カラム名のシンボル], presence: true
と記述します。
class User < ApplicationRecord validates :name, presence: true validates :email, presence: true end
このようにvalidatesは、第1引数にカラム名のシンボル、第2引数以降にバリデーションの種類を指定します。
バリデーションが有効になっていることをrailsコンソール上で確認してみましょう。
$ bin/rails c
↓
irb(main):001:0> user = User.new => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil> irb(main):002:0> user.valid? => false irb(main):003:0> user.errors.full_messages => ["Name can't be blank", "Email can't be blank"] irb(main):004:0> user.save (0.3ms) BEGIN (0.2ms) ROLLBACK => false
railsコンソールの1行目でUserモデルのインスタンスをnewし、userという変数に格納しています。2行目のvalid?メソッドはActiveRecordが提供するメソッドで、バリデーション結果を返却してくれます。ここではnameとemailが空なのでuser.valid?がfalseで返却されているのが分かるでしょう。3行目はuser.errors.full_messagesと記述することで、バリデーションエラーメッセージを確認しています。nameとemailが空だと許容されないエラーメッセージが表示されます。4行目ではsaveしていますが、バリデーションエラーが発生しているので当然saveできず、falseが返却されています。
lengthバリデーションの追加
本連載の第2回では、マイグレーション後にPostgreSQLクライアント上でusersテーブルを確認しました。nameとemailは「character varying」となっています。varyingの数値指定がないのでPostgreSQLでは文字列長の制限はありません。実用的には255文字程度あれば十分だと考えられますので、name、email共に255文字の文字列長制限をバリデーションで表現しましょう。
Userモデルに以下の記述を追加します。
class User < ApplicationRecord validates :name, presence: true, length: { maximum: 255 } validates :email, presence: true, length: { maximum: 255 } end
validatesの第3引数にlengthを追加しました。このように記述することで最大255文字までを許容し、256文字以上ではバリデーションエラーが発生するようになります。
バリデーションが正しく動作することをrailsコンソール上で確認してみましょう
$ bin/rails c
↓
irb(main):001:0> name = 'a' * 255 => "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" irb(main):002:0> email = 'b' * 256 => "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" irb(main):003:0> user = User.new name: name, email: email => #<User id: nil, name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", email: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb...", created_at: nil, updated_at: nil> irb(main):004:0> user.valid? => false irb(main):005:0> user.errors.full_messages => ["Email is too long (maximum is 255 characters)"]
nameとemailにそれぞれ255文字、256文字の文字列をセットしてUserインスタンスを生成しています。バリデーションの定義から255文字のnameはOK、256文字のemailはNGとなっている様子が分かります。
formatバリデーションの追加
メールアドレスのフォーマットは、@を含み、@以前のローカル部と@以降のドメイン部で異なります。詳細な定義はRFC 5321や5322という技術標準を定める文書に記述されています。ここでは厳密性を求めず、より実践的な例としてrailsチュートリアルに記述されている正規表現を使用して実装します。
class User < ApplicationRecord validates :name, presence: true, length: { maximum: 255 } 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
VALID_EMAIL_REGEX定数に正規表現を定義し、formatバリデーションを追加し、withで正規表現を指定することでメールアドレスのフォーマットを制限しています。実際にバリデーションが機能していることを確認してみましょう。
$ bin/rails c
↓
irb(main):001:0> user = User.new name: 'test', email: 'test' => #<User id: nil, name: "test", email: "test", created_at: nil, updated_at: nil> irb(main):002:0> user.valid? => false irb(main):003:0> user.errors.full_messages => ["Email is invalid"] irb(main):004:0> user = User.new name: 'test', email: 'test@example.com' => #<User id: nil, name: "test", email: "test@example.com", created_at: nil, updated_at: nil> irb(main):005:0> user.valid? => true
emailを「test」と指定した場合はバリデーションエラーが発生し、「test@example.com」と指定した場合はバリデーションエラーが発生しない様子が分かるでしょう。