开发者

Ruby on Rails: How do I change the behavior of RecordNotFound?

When going to on object's show page with an id that doesn't exist, the RecordNotFonud exception is thown. Is there a way I can redirect to some error page, or maybe a different action when开发者_Go百科 this error is thrown?


You may use rescue_from if you are using Rails 3:

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, :with => :render_404

  def render_404
    respond_to do |format|
      format.html { render :action => "errors/404.html.erb", :status => 404 }
      # and so on..
    end
  end
end

Yes, you can also do a redirect instead of render, but this is not a good idea. Any semi-automatic interaction with your site will think that the transfer was successfull (because the returned code was not 404), but the received resource was not the one your client wanted.


In development mode you'll see the exception details but it should automatically render the 404.html file from your public directory when your app is running in production mode.


See http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html. Rails has nice features for exception handling.


I generally do something like this in my ApplicationController

class ApplicationController < ActionController::Base
    rescue_from ActiveRecord::RecordNotFound, :with => :routing_error

    private
    def routing_error
        redirect_to(root_url, :alert => "Sorry, the page you requested could not be found.")
    end
end


If you need to handle more than one specific exception, use rescue_action or rescue_action_in_public, the difference in to hook local requests or not (development/production in common). I prefer to use in_public , because need to review exception's backtrace in development mode.

take a look at my source code:

class ApplicationController < ActionController::Base
  include CustomExceptionsHandler
  ....

end


module CustomExceptionsHandler

  # Redirect to login/dashboard path when Exception is caught
  def rescue_action_in_public(exception)
    logger.error("\n !!! Exception !!! \n #{exception.message} \n")

    case exception.class.to_s
    when "Task::AccessDenied"
      logger.error(" !!! 403 !!!")
      notify_hoptoad(exception) //catch this kind of notification to Hoptoad
      render_403
    when "AuthenticatedSystem::PermissionDenied"
      logger.error(" !!! 403 !!!")
      render_403      
    when "Task::MissingDenied"
      logger.error(" !!! 404 !!!")
      notify_hoptoad(exception)
      render_404
    when "ActionController::RoutingError"
      logger.error(" !!! 404 !!!")
      render_404      
    else
      notify_hoptoad(exception)
      redirect_to(current_user.nil? ? login_path : dashboard_path) and return false
    end
  end


  private


  #403 Forbidden
  def render_403
    respond_to do |format|
      format.html { render :template => "common/403", :layout => false, :status => 403 }
      format.xml  { head 403 }
      format.js   { head 403 }
      format.json { head 403 }
    end
    return false
  end

  #404 Not Found
  def render_404
    respond_to do |format|
      format.html { render :template => "common/404", :layout => false, :status => 404 }
      format.xml  { head 404 }
      format.js   { head 404 }
      format.json { head 404 }
    end
    return false
  end

end


Use a begin - rescue - end construct to catch the exception and do something useful with it.

userid=2
begin
    u=User.find userid
rescue RecordNotFound
    redirect_to "/errorpage"     #Go to erropage if you didn't find the record
    exit
end

redirect_to u           # Go to the user page
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜