Railsのエラー

喉元過ぎれば熱さ忘れるということもあり、あとで同じようなことが起きたときに「あれ、なんだっけ?」とならないようにメモ。エラーメッセージをググって探しにくる人のためになればなおよろし。

NoMethodError (undefined method `params?' for #):

ItemsController には `params?' というようなメソッドはないということで、そのまんまの意味。

  • メソッド名の綴りが間違ってる。他を疑う前にまず自分を疑うこと。
  • module のメソッドの場合、module_function するのを忘れて、public になってない。
  • 同じく module の場合、include していない。
  • Mongrel を再起動しないでテストしてるときは、debugger で止めて、load '???.rb' で明示的にリロードしてやらないと、require もしくは include はリロードされない。(これは結構はまる)

NameError (undefined local variable or method `ken_set' for #):

ローカル変数が定義されていないか、メソッドがないと言われてる。

  • 上のメソッドがない場合とほぼ同様のケース
  • return i if (i=j)>0」のような後置if文を使うケースで、if文の中で変数を定義して、True だったらその変数を使うみたいにやってると、このエラーになる。こういう書き方はNG。ちなみに「if (i=j)>0 then return i end」はOK。

TypeError (ApplicationController is not a module):

自分定義のモジュール名に「module ApplicationController」と付けたら、案の定怒られた。

NoMethodError (You have a nil object when you didn't expect it!

このメッセージの続きは「You might have expected an instance of ActiveRecord::Base. The error occurred while evaluating nil.[]=):」となってる。

  • nil.=」でわかる通り、nil オブジェクトに .= メソッドを適用しようとしてエラーになってる。なにをしようとしていたかというとこんなこと(↓)。
@item = Item.find_by_name(iname)
if @item.blank?
  @item[:name] = iname
  @item.save
end

もちろんこれで動くはずはなく、こっち(↓)が正解。.new で入れ物を作ってから .save すること。

@item = Item.find_by_name(iname)
if @item.blank?
  @item[:name] = Item.new({:name => iname})
  @item.save
end

ActiveRecord::StatementInvalid

続きはこちら(↓)。

(Mysql::Error: You have an error in your SQL syntax; 
check the manual that corresponds to your MySQL server version for the right syntax 
to use near 'Jun 04 17:16:30 +0900 2008) ' at line 1: 
SELECT * FROM `items` WHERE ( updated_at > Wed Jun 04 17:16:30 +0900 2008) ):

一見して SQL の書き方がまずい。find の :conditions にハッシュを使えばこういうことにならないんだけど、自分で WHERE句を文字列として組み立てようとするとこういうはめになる。

Item.find(:conditions => ["updated_at > ?", 1.days.ago]  # ← 正しい
Item.find(:conditions => "updated_at > #{1.days.ago}"    # ← 間違い
Item.find(:conditions => "updated_at > #{1.days.ago.to_s(:db)}" # ← 正しい

to_s(:db)とやると「updated_at > '2008-06-04 17:25:13'」というような文字列を返してくれる。

ActionView::TemplateError (undefined method `merge' for "1":String)

続きは「on line #12 of items/_form.html.erb:」など。

  <%= f.check_box 'cache_on', '1' %><%= f.label 'cache_on', 'キャッシュON' %>

check_boxをチェックされた状態にしたくて適当に'1'とかしてみたらこういうエラー。本当はこう(↓)しないといけなかった。

  <%= f.check_box 'cache_on', {'checked' => 'checked'} %><%= f.label 'cache_on', 'キャッシュON' %>