This post originated from an RSS feed registered with Ruby Buzz
by Agnieszka Figiel.
Original Post: Pretty 404 for Typo
Feed Title: agnessa's blog
Feed URL: http://blog.agnessa.eu/xml/rss/feed.xml
Feed Description: ruby and rails impressions from a beginner developer
Inspired by Jeff Atwood’s “Creating User Friendly 404 Pages” articles, I decided to get one for my blog. Jeff argues that a dynamic 404 page that actually tries to guess what the user might have been looking for has much more value than a static “sorry” page, which usually is the last page an angry user has seen on your site. One important observation is that while there’s absolutely no need to inform the user that it’s a 404 error, it is important that the page is served with a proper 404 status, so that spiders stay away and you don’t get listed in search engine indexes with an error page.
There are several helpful elements a static 404 page can have:
a home page link
a search box
an error report form
a contact form
While this is useful to some users, it requires that the they proceed with some action that could be easily automated for them, like:
run a search basing on the request parameters
suggest most recent / popular material on your site
automatically send an error report – in most cases it will be more informative than whatever the user could provide!
So I decided to incorporate some of these elements in my 404 pages. Since Typo runs on Ruby on Rails, there are basically three contexts in which a 404 error can occur:
Each of these situations needs to be handled separately—in my solution via routes, method_missing in controller and in content display methods (articles_controller.rb), respectively.
Since typo already does 404 management of its own, I needed to hook into it. The malformed controller error is handled via a lowest priority wildcard route:
This maps to the redirect action in redirect controller, which I modified to use my pretty_404 method:
def redirect
r = Redirect.find_by_from_path(params[:from])
if(r)
[...]
else
pretty_404([params[:from]])
end
end
The second type of error can be trapped with method_missing in the controller:
def method_missing(m, *args)
pretty_404([m])
end
The third error is managed in the “view_page” and “display_article” methods in ArticlesController.
The pretty_404 method looks as follows:
def pretty_404(tokens=[])
tokens = tokens.flatten.collect {|t| "%#{t.downcase}%"}
@search_results = Content.find(:all, :conditions => [(["(LOWER(title) LIKE ?)"] * tokens.size).join(" AND ")+(tokens.size > 0 ? " AND " : "")+ "(published=true OR type='Page')", *tokens.flatten], :order => "published_at DESC", :limit => 5)
@popular_items = Content.find(:all,:conditions => "published=true OR type='Page'", :order => "published_at DESC", :limit => 5)
@popular_items-=@search_results
render :file => TypoPretty404::TYPO_PRETTY_404_PAGE, :layout => false, :status => 404 and return
end
The file which is rendered is a custom page, which I wanted to be styled like the rest of my blog. Unfortunately, rendering with layout was not a satisfactory way of achieving this. When rendering with layout, typo tries to render the header and the sidebar; while the header is ok, I wanted to avoid including my cluttered sidebar in the 404 page. However, I couldn’t find a way to suppress rendering the sidebar in the third type of 404 error.
I decided to place the following pieces of information on that page:
the blog header
the search results
recent content links
the search box, in the same position as in the layout
the home link (for those who wouldn’t think of clicking the header)
Initially I was hoping it would be possible to do it in a way that would work well universally with all themes, but so far I failed at that :| Since it is impossible to render with layout, I needed a custom page that would use the stylesheets defined for the theme; the first problem I encountered was that I’m not sure if it’s possible to automatically retrieve stylesheet names for a theme; the next problem is how to arrange the page so that it uses the theme’s color scheme, but is not affected by element positioning, which varies across themes. This is definitely something to work on.