views:

1019

answers:

3

I need to implement a custom error page in my rails application that allows me to use erb.

I've been following this tutorial (http://blog.tommilewski.net/2009/05/custom-error-pages-in-rails/) and I cannot get it to work locally (or remotely). I am running Rails 2.3.5

Here's the gist of the approach.

1) in the 'application_controller', I over ride the "render_optional_error_file(status_code)" method, and set the visibility to "protected", like this.

protected

def render_optional_error_file(status_code)
  known_codes = ["404", "422", "500"]
  status = interpret_status(status_code)

  if known_codes.include?(status_code)
    render :template => "/errors/#{status[0,3]}.html.erb", :status => status, :layout => 'errors.html.erb'
  else
    render :template => "/errors/unknown.html.erb", :status => status, :layout => 'errors.html.erb'
  end
end

def local_request?
  true
end

I also created a folder within views called "errors" and created the following views: 404.html.erb, 422.html.erb, 500.html.erb, unknown.html.erb and I created a new layout "errors.html.erb"

I can't seem to get it to work. I've been trying to trigger the 404 page by navigating to http://localhost:3000/foobar -- but, instead of getting the new 404.html.erb, I seem to be getting the standard apache 500 error. This happens when I try both 'mongrel_rails start' and 'mongrel_rails start -e production'.

+1  A: 

You most likely get the 500 error because of an application error. Have you checked the log files?

Update:

Are you certain that you are running 2.3.5 and not an older version that happens to be installed? Mongrel should say which version you are running when it starts, otherwise it should say in the config/environment.rb file.

There are some errors in the code that might create the 500 error. I've changed that and also corrected a few other things I think you meant :)

def render_optional_error_file(status_code)
  known_codes = ["404", "422", "500"]
  status = interpret_status(status_code)

  if known_codes.include?(status) # Here it should be status, not status_code (which is a symbol)
    render :template => "errors/#{status[0,3]}", :status => status, :layout => 'errors' # No need to mention ".html.erb", you can do it, but it is not necessary since rails will guess the correct format.
  else
    render :template => "errors/unknown", :status => status, :layout => 'errors'
  end
end

def local_request?
  # This must return false instead of true so that the public viewer is called 
  # instead of the developer version.
  false 
end
Jimmy Stenke
what I'm saying is that this application error is caused by the rooting error
marcgg
ok you're right! I removed my question since it wasn't accurate anymore and I'm really not sure what's the OP's problem. Thanks for the enlightment ^^
marcgg
yes, I appear to be getting a routing error ...here's what I see when I tail the dev logs;Processing ApplicationController#index (for 127.0.0.1 at 2010-02-10 12:35:35) [GET]ActionController::RoutingError (No route matches "/foobar" with {:method=>:get}): Rendering rescues/layout (not_found)/!\ FAILSAFE /!\ Wed Feb 10 12:35:35 -0500 2010 Status: 500 Internal Server Errorhow can I fix this? And subsequently test to see if it's working?
rsturim
hmm, have you corrected the paths as I've suggested?I believe that it is something in that method that is triggering the 500 error. I am not certain on why you don't get a trace of it, but it is probably because that method is supposed to handle it as well.
Jimmy Stenke
+4  A: 

I would suggest using exceptions to render such error pages, so you can use inheritance to group your error messages...

First, declare some (I usually do it in application_controller.rb)

class Error404 < StandardError; end
class PostNotFound < Error404; end

Then add code to ApplicationController to handle them

class ApplicationController < ActionController::Base

  rescue_from ActionController::RoutingError, :with => :render_404
  rescue_from Error404, :with => :render_404
  rescue_from PostNotFound, :with => :render_post_not_found


  def render_404
    respond_to do |type| 
      type.html { render :template => "errors/error_404", :status => 404, :layout => 'error' } 
      type.all  { render :nothing => true, :status => 404 } 
    end
    true
  end

  def render_post_not_found
    respond_to do |type| 
      type.html { render :template => "errors/shop_not_found", :status => 404, :layout => 'error' } 
      type.all  { render :nothing => true, :status => 404 } 
    end
    true
  end
end

This renders errors/error_404 with the errors layout. Should get you started :)

And in your target_controller:

raise PostNotFound unless @post
galileoMonkey
Just what I was looking for!
SamStephens
A: 

Firstly - have you deleted the file: 'public/500.html' If that file exists, it will override anything else that you try to do.

Secondly, using an explicit "rescue_from" in the controller (as explained in the other comment) - is a good option if you need to fine-tune the response to different kinds of errors.

Taryn East