程序运行中难免遇到异常,当系统抛出异常后,Rails会显示如下的一个页面。在开发过程中你经常会看到。
显示异常信息的页面。
这个页面中列出错误信息及异常堆栈。第一眼看过去可能有点晕,不过这些信息会为你定位问题提供很大的帮助(页面比较长,截图是其中的一部分)。在具体分析眼前这个错误之前,先介绍一下什么是异常堆栈。
什么是异常堆栈?
在irb中,我们抛出一个异常。Ruby框架会根据异常出现的位置显示异常堆栈:
>> raise "test error"
RuntimeError: test error
from (irb):1
>>
这个异常堆栈很短只有一行。如果将这个异常从一个方法中抛出,会怎么样呢?
>> def foo
>> raise "test error"
>> end
=> nil
>> foo
RuntimeError: test error
from (irb):3:in `foo’
from (irb):5
>>
调用这个包含异常的方法后,显示了异常堆栈,方法的名字位于异常的下方。再将这个方法被另一个方法调用看看。另一个方法的方法名被列在了之前那个方法名的下面一行。
>> def bar
>> foo
>> end
=> nil
>> bar
RuntimeError: test error
from (irb):3:in `foo’
from (irb):7:in `bar’
from (irb):9
>>
bar
方法调用foo
方法,其中在foo
方法中产生了异常。显示的异常堆栈里,越靠近异常的方法,越靠上方。了解了异常堆栈,回到最初的那个实际问题上。
进行异常调试
异常堆栈的最前面几行为
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2578:in ‘attributes=’
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2283:in ‘initialize’
app/controllers/tasks_controller.rb:7:in ‘new’
app/controllers/tasks_controller.rb:7:in ‘show’
最上面几行显示说错误发生在Rails框架内部,虽然确实如此,但往往框架内部出错的原因是由于我们的外部误用造成的。在我们的代码中找找原因,继续往下看便是我们的代码。TaskController
类中的show
方法我们本想从数据库中查询出任务对象,却使用了Task.new
方法。
class TasksController < ApplicationController
def index
@tasks = Task.find(:all, :include => :project)
end
def show
@task = Task.new(params[:id])
end
end
TaskController
类代码,其中show
方法中包含错误。
将Task.new
改为Task.find
之后,重新加载页面看看是不是对了。
恩,在异常堆栈的指引下,我们找到了问题所在。如果你正在使用TextMate这里再附赠一个调试中可以使用的小窍门。一个名叫Rails Footnotes的插件可以将异常堆栈中显示的行变成链接,点击链接就可以直接打开对应的文件。可以在Rails应用的根目录执行下面的命令安装。(依赖git软件)。
git clone git://github.com/drnic/rails-footnotes.git vendor/plugins/footnotes
rm -rf vendor/plugins/footnotes/.git