第4回 Active Recordの入力チェック機能
第4回 Active Recordの入力チェック機能
連載第4回は、Railsの入力チェックを取り上げます。Rails3からは、Modelに対して入力チェックを簡潔に記述できるようになりました(Rails2以前の入力チェックも使用可能)。そこで、前回作成したアプリケーションに対して、入力チェックを実装してみましょう。なお、前回の記事で予告した簡単な商品購入ページの作成ですが、記事のボリュームが大きくなってしまうので、別の連載で書くことにしました。お詫びいたします。
入力チェック機能の概要
さて、Railsにおける入力チェックですが、「ActiveRecord::Base」を継承したModelに、後ほど説明する入力チェックを入力項目ごとに実装しておくと、以下のメソッドを呼び出したときに入力チェックが実行されます。
- create
- create!
- save
- save!
- update
- update_attributes
- update_attributes!
メソッド名の末尾に「!」が付いているものは、無効なデータが渡されたときに例外を発生させます。 また、以下のメソッド名は、入力チェックが実装されていたとしても、入力チェックが実行されません。
- decrement!
- decrement_counter
- increment!
- increment_counter
- toggle!
- touch
- update_all
- update_attribute
- update_column
- update_counters
■ コラム:「Ruby」における「!」マークがついたメソッドのお話
読者の中には、Rubyに触れること自体が初めてという方もおられるでしょう。ここでは、String#chopとString#chop!を使って、Rubyにおける「!」マークがついたメソッドとそうでないメソッドの動作について説明します。 chopは、文字列の末尾から1文字を取り除いた結果を返却するメソッドです。しかし、「!」マークがつくと少し結果が変わります。下記に示す、オブジェクト(str)の変化をご覧ください。 str = "Hello World!" str.chop => "Hello World" puts str => “Hello World!” str.chop! => "Hello World" puts str => “Hello World”(末尾の1文字が除かれている) chopを実行したあとに対象の文字列を出力しても(puts str)、元の値に変化はありません。しかし、chop!を実行すると、元の値にも変化が発生します(str.chop!後のputs str)。 このように、Rubyにおいて「!」マークのついたメソッドは、元の値を変化させてしまう性質があります。これを破壊的メソッド(destructive method)と呼びます。Railsにおいても、「!」マークのついたメソッドは破壊的メソッドですが、例外を発生させる/させないという意味で使用することがあります。 |
未入力チェック機能を実装してみよう
では、はじめに未入力チェックを実装してみましょう。まずは、前回作成したアプリケーションのフォルダに移動します(筆者は、「rails_article_work」配下の「lesson03」に移動します)。
$ cd rails_article_work/lesson03 |
次に「app/models/user.rb」を開いてください。そして、user_name要素に未入力チェックをつけるため、以下のように編集します(赤字部分)。
class User < ActiveRecord::Base
validates :user_name, :presence => true
end
|
ファイルを保存したあと、サーバーを起動しましょう。
$ rails server |
そして、ブラウザからhttp://127.0.0.1:3000/users/newを開いてください。 さて、新規ユーザー登録画面で各項目に値を入力していくわけですが、「User name」のみ空白にして、「Create User」ボタンをクリックしてみてください。
図 1 新規ユーザー登録をするところ
図 2 User nameの入力チェックが実行されたところ
いかがでしょう?上図の通りに入力チェックが実行されましたか? 少しだけ解説すると、「app/controllers/users_controller.rb」の以下の箇所(赤字部分)で「save」メソッドが呼ばれ、先ほど定義した入力チェックが実行されました。
class UsersController < ApplicationController
・・・省略・・:
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
format.html { redirect_to(@user, :notice => 'User was successfully created.') }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
・・・省略・・:
end
|
ちなみに、「@user(インスタンス変数)」の内容は、「app/views/users/_form.html.erb」を参照すると分かります。
入力値の長さをチェックしてみよう
次は、項目に入力された値の長さをチェックして、指定した長さを下回るか、もしくは超えていたらエラーを表示するようにしてみましょう。先ほどと同じく「app/models/user.rb」を開いてください。そして、以下のように編集します(赤字部分)。
class User < ActiveRecord::Base
validates :user_name, :presence => true
:length => {:minimum => 2, :maximum => 10}
end
|
ファイルを保存したあと、新規ユーザー登録画面を開きます。User nameに対して全角または半角で1文字入力するか11文字以上を入力して、Create Userボタンをクリックしてみてください。下図は、入力値が短いときの入力チェックと、入力値が長いときの入力チェックが実行されたところを表しています。 最初は、入力値が短いときの入力チェックです。
図 3 1文字入力して新規ユーザー登録するところ
図 4 User nameの長さチェック(入力値が短い)が実行されたところ
続いて、入力値が長いときの入力チェックです(入力チェック実行前の図は省略)。
図 5 User nameの長さチェック(入力値が長い)が実行されたところ
いかがでしょう?上図の通りに入力チェックが実行されましたか?
メールアドレスの書式をチェックしてみよう
Railsには、いくつかの入力チェック機能がありますが、最後はメールアドレスの書式をチェックして、指定した書式ではない場合はエラーを表示するようにしてみましょう。先ほどと同じく「app/models/user.rb」を開いてください。そして、以下のように編集します(赤字部分)。
class User < ActiveRecord::Base
validates :user_name, :presence => true
:length => {:minimum => 2, :maximum => 10}
validates :mail_address, :format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i}
end
|
ファイルを保存したあと、新規ユーザー登録画面を開きます。User nameに対して適当な値(メールアドレス書式でない文字列)を入力後、Create Userボタンをクリックしてみてください。下図では、「user4@!"#$.&'」と入力してみました。
図 6 メールアドレスを入力して、新規ユーザー登録するところ
図 7 Mail addressのメールアドレス書式チェックが実行されたところ
いかがでしょう?フォーマットに指定した正規表現パターンを編集すれば、様々なメールアドレス書式に対応できます。また、メールアドレスに限らず、別の項目の書式チェックに応用できます。 あらためて、Railsの入力チェックは下記の通りとなります。
表 1入力チェック一覧
:presence => true | 未入力のチェックを行う |
:length => { :minimum => 2, maximum=> 10 } | 指定された値の長さをチェックする |
:format => {:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i} | 書式のチェックを行う |
:acceptance => true | 規約同意などのチェックボックスがチェックONにされているかを検証する |
:confirmation => true | パスワードなどの確認入力項目が、比較元項目と一致しているかチェックを行う |
:exclusion => { :in => %w(www us ca jp) } | 指定された値が含まれないことをチェックする |
:inclusion => { :in => %w(small medium large) } | 指定された値が含まれることをチェックする |
:numericality => { :only_integer => true } | 入力値が数値であるかチェックする |
:uniqueness => true | 入力値がユニークであるかチェックする |
本連載では、これらのすべてを紹介することは省略しますが、興味のある方は試してみてください。
補足
Railsでは、独自の入力チェックを作成することが可能ですが、今回は割愛させていただきます。興味のある方は、下記の公式ドキュメントやブログを参照するとよいでしょう。
- http://guides.rubyonrails.org/active_record_validations_callbacks.html
- http://lindsaar.net/2010/1/31/validates_rails_3_awesome_is_true
- http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/
また、入力項目がテーブルに存在しない項目であったとしても、ヘルパーを使って仮想属性を作成することにより、入力チェックを実現することが可能です。詳しくは、上記にあげた公式ドキュメントのURLをご参照ください。
おわりに
連載第4回目はいかがだったでしょうか。入力チェックも非常に簡単に実現でき、しかもよく使うパターンがあらかじめ用意されているので、実現方法の検討が大幅に省略できます。もっと詳しく知りたい方は、下記の公式ドキュメントをご参照ください。
さて次回は、Ajaxについて触れてみたいと思います。お楽しみに!
第4回 おしまい
※.記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。