根据不同的 application exception 提供不同的解决方式(比如 redirect user 或 render 特定的页面 )是很常见的设计模式。在这个 更新系列 之前我们经常需要在 controller 里超量加载 rescue_action_in_public method:
class PostsController < ApplicationController
def rescue_action_in_public(exception)
case(exception)
when ActiveRecord::RecordNotFound then render :file => '/bad_record'
when NoMethodError then render :file => '/no_method'
else render :file => '/error'
end
end
end
很容易发现这段代码立即被扩展成了多组乱了套的 if/else 声明。
现在我们拥有了一套非常简洁的方法来通过新的 rescue_from 来铺展不同的 exception 与 handler 脉络。 rescue_from 使一个 exception 的类型与一个 handler 的方法名称直接栓到一起,使得exception的处理变得更加简单易懂:
class PostsController < ApplicationController # 从 exception 到 handler methods 的声明 rescue_from ActiveRecord::RecordNotFound, :with => :bad_record rescue_from NoMethodError, :with => :show_error def bad_record; render :file => '/bad_record'; end def show_error(exception); render :text => exception.message; end end
请记住,exception handler methods 既可以作为无实参的 method, 也可以添加一个 问题形式的 exception 作为实参 (如上面的 show_error 所示)。
您也可以 使用 block 或者 proc 来设置 rescue_from 里的 exception处理方式:
class PostsController < ApplicationController
# 从 exception 到 handler methods 的声明
rescue_from(ActiveRecord::RecordNotFound) { |e| render :file => '/bad_record' }
rescue_from NoMethodError, :with => proc { |e| render :text => e.message }
end
感谢 Yudi 提供本系列文档
原文作者是 Ryan Daigle, 请访问他的博客