根据不同的 application exception 提供不同的解决方式(比如 redirect user 或 render 特定的页面 )是很常见的设计模式。在这个 更新系列 之前我们经常需要在 controller 里超量加载 rescue_action_in_public method:
1 2 3 4 5 6 7 8 9 |
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的处理变得更加简单易懂:
1 2 3 4 5 6 7 8 9 10 |
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处理方式:
1 2 3 4 5 6 7 |
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 |



