ActiveRecordは属性の値がデータベースに反映される前に適切であるかを検証するバリデーションの仕組みも用意しています。以下に属性が空でないことを検証するバリデーションの例を示します。
class User < ActiveRecord::Base validates :name, :department, presence: true end User.create(name: 'イブ', department: '人事部') # 保存される User.create(department: '人事部') # 保存されない
バリデーションはデータベースにデータを保存・更新するメソッド、すなわち「create(create!)」「save(save!)」「update(update!)」を呼び出したときに実行されます。「!」付きのメソッドはバリデーション失敗時に例外を発生します。
オブジェクトがバリデーションを実行し失敗すると、オブジェクトは「errors.messages」メソッドでエラーの内容を教えてくれます。
u = User.create(department: '人事部') u.errors.messages # => {name:["can't be blank"]}
また、特定の属性について調べたいときは次のようにします。
u.errors[:name] # => ["can't be blank"]
さらに、全ての属性のエラーを一次元の配列で得る「errors.full_messages」というメソッドも用意されています。この仕組みを用いて、Railsのscaffoldで生成されたオブジェクトのフォームは次のようにしてバリデーションエラーを通知しています。
<%= form_for(@book) do |f| %> <% if @book.errors.any? %> <div id="error_explanation"> <h2> <%= pluralize(@book.errors.count, "error") %> prohibited this book from being saved: </h2> <ul> <% @book.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %>
ここではActiveRecordが用意しているバリデーションでよく使われるものを紹介します。
validatesメソッドは属性に対して複数のバリデーションを設定できます。また、1つのvalidatesメソッドでバリデーションを掛ける属性も複数指定できます。
validatesメソッドはバリデーションの種類をハッシュのキーとして指定します。取り得る値はバリデーションによって異なりますが、いずれのバリデーションでも「:on」「:message」をキーとするハッシュとすることができます。
:onは値に「:create」か「:update」をとり、バリデーションを実行するタイミングを新規保存時か更新時のいずれかに限定します。:messageはデフォルトのエラーメッセージを値の文字列に変更できます。
presenceのバリデーションは対象の属性の値が空でないかを検証します。
validates :name, presence: true
lengthのバリデーションは指定した属性の長さを検証します
# nameが2文字以上・32文字以下であるかを検証 validates :name, length: { minimum: 2, maximum: 32, message: '2文字以上・32文字以下としてください' }
lengthは次のオプションをとります。
formatのバリデーションは指定した属性が正規表現にマッチするかを検証します。
# zip_codeが適切なフォーマットであるかを検証 validates :zip_code, format: { with: /^\d{3}\-?\d{4}$/ }
このように、「with」オプションに正規表現オブジェクトを渡すと、それにマッチするかを検証してくれます。
uniquenessのバリデーションは指定した属性がデータベース中で重複がないかを検証します。
# emailに重複がないかを検証 validates :email, uniqueness: true
numericalityのバリデーションは指定した属性が数値であるかを検証します。
validates :average, numericality: true validates :last_score, numericality: { only_integer: true }
「only_integer」オプションを渡すと、整数であるかも検証してくれます。
inclusionのバリデーションは指定した属性が配列または範囲に含まれているかを検証します。
validates :age, inclusion: { in: 0..19, on: :create }
この他にも以下のバリデーションが用意されています。
validatesメソッドには、さらに便利なオプションを渡すことができます。
validates :zip_code, format: { with: /^\d{3}\-?\d{4}$/ }, allow_nil: true
シンボルを渡すと、その名前のメソッドが実行され、返り値が判定に用いられます。文字列の場合は、Rubyのコードとして実行され、その結果が判定に用いられます。
validates :tel, presence: true, if: :contact_by_phone? validates :company, presence: true if: "name.nil?" def contact_by_phone? contact_type == 'phone' end
またifとunlessオプションにはProcオブジェクトを渡すこともできます。
以下に挙げるメソッドなどはバリデーションをスキップします。
Railsのバリデーションの機能は豊富で、標準のものだけでも事足りることがほとんどです。それでもカスタムバリデーションを作りたい場合には、そのための仕組みも用意されています。
また、次回紹介する「モデル間の関連」の機能と併せて関連先・関連元のオブジェクトのバリデーションを行うこともできます。ですが、それらの機能が必要になるケースはそう多くはないため、必要になったときに身に付けるのがいいでしょう。
今回はActiveRecordの基本的な機能とマイグレーション、そしてバリデーションについて紹介しました。ActiveRecordの体系は巨大ですが、いずれの機能もアプリケーションの設計の上でとても重要です。
次回はモデル間の関連とコールバックについて解説していきます。お楽しみに。
林 慶(Rails技術者認定シルバー試験問題作成者)
平成2年大阪生まれ。2006年から高専で情報工学を学んでいたが当時は所謂プログラミングができない工学生だった。卒業後、高専の専攻科に上がったもののマンネリ化したキャンパスライフに飽きたため休学して渡豪。そこでプログラミングに対するコンプレックスを克服するためにRuby on Railsなどでアプリケーションを作ることを覚える。
帰国後から現在までは復学し推薦システムに関する研究を行いながら、アジャイルウェアでRuby on Railsアプリケーションの開発業務に従事している。
好きなメソッドはinject。
山根 剛司(Ruby業務開発歴7年)
兵庫県生まれ。1997年からベンチャー系のパッケージベンダーで10年間勤務。当時、使用していた言語はJavaとサーバーサイドJavaScript。
2007年よりITコンサル会社に転職し、Rubyと出会って衝撃を受ける。基幹システムをRuby on Railsで置き換えるプロジェクトに従事。それ以来Ruby一筋で、Ruby on Railsのプラグインやgemも開発。
2013年より、株式会社アジャイルウェアに所属。アジャイルな手法で、Ruby on Railsを使って企業向けシステムを構築する業務に従事。
Ruby関西所属。好きなメソッドはtap。
Twitter:@spring_kuma、Facebook:山根 剛司
Copyright © ITmedia, Inc. All Rights Reserved.