モデルのバリデート

  • モデルの検証機能だね!
    • ActiveRecord::Validations::******Validatorクラスを使うのかな?
      • 細かい機能は、P227参照!
  • 基本的な使い方は、単にモデルでvalidatesとしてルールを宣言するだけ
    • こんな感じね。
      class Book < ActiveRecord::Base
       validates :isbn,
         :presence => true,        # 空チェック
         :uniqueness => true,      # 一意チェック
         :length => { :is => 17 }, # 文字数チェック
         :format => { :with => /^[0-9-]*$/ } # 正規表現チェック
       validates :price,
         :numericality => { :only_integer => true, :less_than => 10000 } # 数値チェック
      end
      
    • あ、エラー時は、URLが「books/new」から「books」になるのか。後で調べよう!
  • Rails2では、validates_****って名前の検証ヘルパーだったけど、Rails3はvalidatesメソッドを使うらしい
    • この新しいRails3の記法は、 「Sexy Validation」 と言うらしいw。セクシーか?
  • で、このvalidatesは、saveメソッドの実行時に動くみたい
    • その他、create/create!/save!/update/update_attributes/update_attributes!でも動くけど、以下のは動かないから注意!
      • decrement/decrement_counter/increment!/increment_counter/toggle!/update_attribute!/update_counters/save(:validate=>false)
    • はー、バリデートは、update_attributesは動くけど、update_attribute!は動かないのは覚えておかないとね!
  • Scaffoldingではのbooksのエラー出力は、app/views/books/_form.html.erbで実際にはこんな感じで出てる
     <% 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 %>
    
    • 要するに、@book.errors.any?でエラーの有無をチェックして、@book.errors.full_messagesをeachで回してメッセージを表示してるんだ。
      • pluralizeはビューヘルパーで、数値の単数形/複数形をチェックするみたい。@book.errors.countでエラー数をチェックしてるんだけど、日本語だと意味なさそう…。
    • で、実際のエラー時のHTMLは、こんな感じで出る
         <div id="error_explanation">
           <h2>2 errors prohibited this book from being saved:</h2>
           <ul>
             <li>Isbn is the wrong length (should be 17 characters)</li>
             <li>Price must be less than 10000</li>
           </ul>
         </div>
      
      • この例だと、isbnとpriceがエラーね。
    • 更に、各項目が赤くなったりしてる所は、こんな感じでスタイルが変更される
       <div class="field">
         <div class="field_with_errors"><label for="book_isbn">Isbn</label></div><br />
         <div class="field_with_errors"><input id="book_isbn" name="book[isbn]" size="30" type="text" value="978-4-7980-2812" /></div>
       </div>
       <div class="field">
         <label for="book_title">Title</label><br />
         <input id="book_title" name="book[title]" size="30" type="text" value="" />
       </div>
       <div class="field">
         <div class="field_with_errors"><label for="book_price">Price</label></div><br />
         <div class="field_with_errors"><input id="book_price" name="book[price]" size="30" type="number" value="1000000" /></div>
       </div>
      
      • この例だと、Titleは正しくて、isbnとpriceがエラーね。
      • スタイルは、field_with_errorsでエラーっぽくなるのねー
      • このCSSはscaffolds.cssで、こんな感じで定義されてるよ
        .field_with_errors {
          padding: 2px;
          background-color: red;
          display: table;
        }
        
  • 他にもいろんなバリデートがあるよー
    :inclusion 候補チェック
    :acceptance 利用規約とかの同意チェック DBにカラム不要
    :confirmation 別項目との同一チェック パスワードの再入力など、DBカラム不要
    :uniqueness 一意性チェック 複数カラムをwhere句みたいに指定も可能
    • 共通パラメータもいっぱいあるよ。P236参照ね
  • 当然、自作のバリデートも使えるよー
    • まずは、ISBNのバリデート用クラス作る場合、app/models/isbn_validator.rbとして、こんな感じで書く
      # coding: utf-8
      
      class IsbnValidator < ActiveModel::EachValidator
       def validate_each( record, attribute, value )
         record.errors.add(attribute, 'は正しく無いよ!') unless value =~ /^[0-9-]*$/
       end
      end
      
      • 大事なのはクラスの命名規則で、検証名Validatorって書く必要あり。
    • で、後は、モデル側でここの3行目みたいに追加すればOK
      class Book < ActiveRecord::Base
       validates :isbn,
         :isbn => true,            # ここが自作バリデートね
         :presence => true,        # 空チェック
      
      • すっごい簡単だなー。素晴らしい!
    • 当然、パラメタ指定も可能で、validate_each側で「:options[パラメタ名]」で取れるよ!
    • 他のカラムにアクセスするには、以下の2つの方法で。
      • 当然、普通のレコードのオブジェクトに名前を指定してのアクセス
        field = record.title
        
      • こっちは、record.attributesでの指定ね。これだと、オプション指定とかの文字列でのアクセスも可能みたい
        field = record.attributes[options[:compare_to]]
        
    • おお!バリデートクラスを作らずにバリデートもできるんだw
      • 要するに、モデルに直接privateメソッドを書いちゃうパターンね。
      • タイトルの空チェックは、こんな感じかな?
        class Book < ActiveRecord::Base
         validate :title_valid?
         private 
         def title_valid?
           errors.add(:title, 'は空じゃ駄目だよ!') unless !title.empty?
         end
         ----以下略----
        

-
最終更新:2011年12月22日 07:25