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 }
English
Italiano