Removing wildcard routes

08/06/2012 engineering

Target: remove the :controller/:action(/:id) routes from config/route.rb.

Problem: make sure we have complete route coverage.

Well, the problem can be solved in two ways:

  • Go into every controller and translate each action to a routing spec.
  • Parse last week's logs and check whether each url is routable.

The first solution sounds easy but the second one sounds more fun. :-)


  • Remove the wildcard routes from config/routes.rb:

    The offending lines look something like this: match ':controller(/:action(/:id(.:format)))'. Get rid of them.

  • Get a few days' worth of haproxy.log (or some other log):

    Just ask your admin for that.

  • Take a random sample out of it:

    Usually cat ~/Logs/haproxy.log | shuf -n 1000 >> test/fixtures/logs/requests.log will suffice.

  • Translate each url into a routing spec:

    Use the following sample spec file and edit it to skip known failing urls and fix subdomains.

  • Run the routing specs:

    bundle exec rspec spec/routing/from_log_routing_spec.rb

  • Write some proper routing specs for each logically failing url:

    from_log_routeg_spec.rb only tests that the urls are recognized. You need to write meaningful routing specs that test if the route links to the correct controller and action.

  • Fix routing errors in config/routes.rb:

    After you have your proper routing specs in place, go and edit your routes.rb. The reason we edit after we write specs is to make sure that the specs work as expected and the edit solved the failure.

  • Get a new random sample and repeat the rest of the recipe until happy.

Important note

Remember that Rails performs DELETE and PUT requests with an actual POST with some _method=put or _method=delete. This means that the log will not always have the correct HTTP verb.

After deploy, what?

As always, things go wrong and your routing specs won't get you 100% coverage. If you use an exception_notification-type gem you might be fine, 404s will come flocking to your inbox. But...

If you are on Rails 3.0, the RoutingError exceptions can't be rescued from inside of the application. A sane workaround I found looks like this:

match '*a', :to => 'statics#render_404' 

Put this at the bottom of your routes (but inside the route.draw block) and link it to an appropriate controller. The controller action should look something like this:


Good luck and good routings!

Ποιοι είμαστε


Η Skroutz Α.Ε. ιδρύθηκε το 2005 και δραστηριοποιείται στην ανάπτυξη καινοτόμων υπηρεσιών τεχνολογίας, δημιουργώντας πρωτοποριακές πλατφόρμες ηλεκτρονικού εμπορίου και ιστοσελίδες υψηλής απόδοσης.

Με έδρα την Αθήνα, η Skroutz Α.Ε. είναι το κορυφαίο digital brand πίσω από τη δημιουργία και την εξέλιξη των δυνατοτήτων της πρωτοποριακής μηχανής αναζήτησης και σύγκρισης τιμών και προϊόντων Η εταιρεία παρέχει ένα εύρος χρηστοκεντρικών λύσεων λογισμικού και πλατφόρμων ηλεκτρονικού εμπορίου αξιοποιώντας νέες τεχνολογίες και μεθοδολογίες, που αναδεικνύουν το πάθος του ανθρώπινου δυναμικού της.