How can I give my app meaningful URLs?

Back in the dark mists of time, when dinosaurs ruled the earth and Rails had a rival framework known as Merb (I’m showing my age now), a concept known as Restful Routing was introduced.

(By the way, I’m English, so I pronounce it as “root”, not “rowt”).

The idea was simple – the web is all about accessing resources; normally documents of an HTML nature. So the URLs (and hence the routes) in a Rails app should reflect that. If one resource lives “within” another resource, then the URL should reflect that as well.

So if you wanted to find out about a person called Kim, you would visit https://example.com/people/kim and if you wanted Kim’s address (this app is creepy) you would visit https://example.com/people/kim/addresses/home.

In your Rails app, you would represent this thusly:

And for your models:

Note the use of to_param in the two models – normally Rails shows an ActiveRecord model’s database ID in the URL – so something like https://example.com/people/8345/addresses/43745 – which is pretty baffling to most people. Of course, we need to make sure that the param you’re using can be uniquely identified (hence the uniqueness validation on username and address_type), so when you adjust your controllers to find by the parameter, it locates the desired record and just that desired record.

So, a basic Rails app would find the person by ID @person = Person.find params[:id] – but in our case, params[:id] is going to contain “kim”, not “8345”. Hence @person = Person.find_by! username: params[:id]. We use Person.find_by! (with an exclamation mark) not Person.find_by (without) because then it will raise an exception if nothing is found.

In the addresses controller, as it’s nested within the person controller, it’s going to be given params[:id] (holding an address-type, such as “home” or “work”) and a params[:person_id] (holding a username, like “kim” or “james” or “hotdude73463”). So to find the person, we do the same as in the person controller (but using person_id) and then use that person to limit our address search (we only want to find addresses belonging to this particular person, so we “walk” down the hierarchy and limit the scope of our searches).

Given that your URLs are actually a hidden user-interface to your application (and remember that Google looks at URLs for SEO signals as well), this use of to_param is a really easy way of making your app that tiny bit more user-and-search-engine-friendly.

1 Comment How can I give my app meaningful URLs?

  1. Pingback: Why is it considered a bad practice to have deeply nested resources? | The Art and Science of Ruby

Comments are closed.