Shoeisha Technology Media

CodeZine(コードジン)

記事種別から探す

Rails 5で実用的なユーザー登録機能を実装

サンプルコードで学ぶRuby on Rails 5実践入門 第4回

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2017/02/16 14:00

 前回は、scaffoldで自動生成したソースコードと実際の動作を関連付けて各アクションについて解説しました。今回は、scaffoldで自動生成したユーザー登録機能をより実践的に拡張していきます。

目次

ユーザー登録時のバリデーションを追加(1)

 scaffoldで自動生成したUserモデルを確認すると分かる通り、まだ何も処理が記述されていません。実際にユーザー登録をする際には以下の要件が必要となるでしょう。

  • 名前(name)とメールアドレス(email)が必須
  • name、emailの文字数制限
  • emailの形式チェック
  • emialは大文字・小文字を区別しない

 これら値のチェック機構をバリデーションと呼びます。Railsではモデルが継承するActiveRecordの機能としてバリデーション用のDSL(Domain Specific Language)が用意されています。これらを利用してバリデーションを実装していきます。

presenceバリデーションの追加

 name、emailはユーザー登録時に空で登録することはできない、ということをバリデーションで表現するには、

validates [カラム名のシンボル], presence: true

と記述します。

リスト1 app/models/user.rb
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モデルに以下の記述を追加します。

リスト2 app/models/user.rb
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チュートリアルに記述されている正規表現を使用して実装します。

リスト3 app/models/user.rb
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」と指定した場合はバリデーションエラーが発生しない様子が分かるでしょう。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • WINGSプロジェクト 竹馬 力(チクバ ツトム)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2012年2月時点での登録メンバは37名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:サンプルコードで学ぶRuby on Rails 5実践入門

おすすめ記事

All contents copyright © 2006-2017 Shoeisha Co., Ltd. All rights reserved. ver.1.5