RSS
 

Archive for November, 2009

Manage routing errors

20 Nov

Our application can only respond to certain requests, of course, to those that we have anticipated. For all other generates an error depending on the type:

  • Routing errors
  • Errors inside the controller

Routing errors

Small premise: In a traditional application, to retrieve a nonexistent page from the web server, we received a code 404. In a framework with a pattern mvc instead, requests through controllers and this allows us to define the behavior. The requests are performed according to the routing rules and in Rails for convention, all the controllers can be addressed. If we open the file routes.rb, at the bottom we discover why:

#configroutes.rb
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'

To ensure that only certain controllers can be routed, just delete those two lines at the bottom of the file that only defines the form of the request, leaving only the explicit routes. End of the preface.

If there isn’t a route, this generates a routing error because Rails does not know what we want. To handle this event, simply add one last road before you generate the error, which will inform them that has not found other valid roads:

#configroutes.rb
 
#at the bottom
map.catch_all "*anything" , :controller => "home" , :action => "unknown_request"

We saw how catch the not handled routes and directs it to the controller where we want to manage it, for that example at home controller using the method unknown_request:

#appcontrollershome_controller.rb
def unknown_request
  respond_to do |format|
    format.html do
      flash[:error] = I18n.t(:unknown_request)
      redirect_to root_path
    end
    format.xml  {  render :xml => {:root => I18n.t(:unknown_request) }, :status => :unprocessable_entity }
  end
end

Errors inside the controller

If the controller has been addressed, does not mean that the request is correct, because each has a series of operations that must exist and must be able to operate on the resource and manage the exceptions raised by the database.

Since version 2.0 of Rails, we can use “rescue_from” in the controller:

#appcontrollersmy_controller.rb
 
class MyController < ApplicationController
  rescue_from ActionController::UnknownAction, :with => :action_not_found
  rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
 
  def action_not_found
    render 'shared/action_not_found', :layout => true, :status => 404
  end
  def record_not_found
    render 'shared/record_not_found', :layout => true, :status => 404
  end
end

Here are the views:

#appviewssharedaction _not_found.html.erb
<h2>Sorry, the action doesn't exists!</h2>
 
#appviewssharedrecord_not_found.html.erb
<h2>Sorry, the record doesn't exists!</h2>

Another more concise way is to pass a proc as a parameter to “rescue_from”:

#appcontrollersmy_controller.rb
rescue_from(ActiveRecord::RecordNotFound) { |e| render 'shared/record_not_found', :layout => true, :status => 404 }
 
Comments Off

Posted in Ruby on Rails