エラーの数え方が違う!

 今回も Ruby on Rails の話です。
 たとえば、@hoge というModelオブジェクトが入ったインスタンス変数があったとします。これは以下のようにして作られたとします。

@hoge = Hoge.new(@params[:hoge])

 これはフォームから入力された値を元にオブジェクトを作るための書き方です。それで、入力値が正しいかどうかは @hoge.valid? で得ることができます。そしてもしこれでエラーがあれば、Viewとなるrhtml内の

<%= error_messages_for 'hoge' %>

の部分にエラーメッセージが表示されます。

 さて、@hoge.valid? が真(正しい)と返す条件は何でしょうか? それは、一通りバリデーションを行って、ActiveRecord::Errors#error.empty? の値が真のときです。つまり、バリデーションでひとつでもエラーがあるとこれは真にはなりません。

 では、error_messages_for で出力されるエラーメッセージの個数はどうやって求められているのでしょうか? 実は、これは ActiveRecord::Errors#error.size で求められるのですが、単純にバリデーションでエラーになった個数が出てくるわけではありません。実質的には、「バリデーションでエラーとなった際に設定されるエラーメッセージの個数」を表わしています。つまり、ActiveRecord::Errors#error.empty? が真であることと、ActiveRecord::Errors#error.size が 0 であることは微妙に意味が違います。

 具体的にいいますと、たとえば「http://wota.jp/ac/?date=20050802#p06」さんを参考に日本語化をしていながらも、ここでコメントアウトしているように、自分のシステムでは必要であるにもかかわらずコメントアウトしっぱなしというような場合、empty? は偽だけれども size は 0 というようなことが起こりえます。

 私は、これですっかりハマりました。皆さんもお気をつけください。