The main entry point to most Web Applications is via HTTP requests through a URL scheme.

A good URL scheme is very important to a web application. URLs should describe the resource, show hierarchy and provide a predictable path through the application for the user.

Rails makes it easy to define your routes to follow the conventions of REST.

In today’s tutorial we will be looking at defining URLs in Ruby on Rails.

Understanding HTTP requests

To really understand how to define a good URL scheme and work effectively with Rails, it helps to have background knowledge of how HTTP requests work.

There are basically 5 HTTP methods for making requests on the Internet, GET, POST, PUT, PATCH, and DELETE.

These HTTP methods map neatly to the common actions that will be performed in a web application:

  • Create POST
  • Read GET
  • Update PUT / PATCH
  • Destroy DELETE

When you want to perform a specific action you should use the correct HTTP method.

For example, if you wanted to get a list of all users in the application, you would make a GET request.

If you wanted to create a new user, you would make a POST request.

If you wanted to update an existing user, you would make a PUT or PATCH request.

The distinction between PUT and PATCH comes down to whether you are updating one of more properties, or completely replacing the resource in one go.

And finally, if you wanted to remove a user you would make a DELETE request.

Where do you define your routes?

To define your routes, Rails has a routes.rb file that is located under the config directory.

If you open that file you will see a massive chunk of comments that provide documentation for how to define your routes. You can have a read through the comments and then just delete them.

You should be left with:

Rails.application.routes.draw do

end  

Having this single location to define routes is good for a couple of reasons, but for me the biggest thing is no matter what rails project you look at, you will always have a good place to start exploring.

How to define a URL

Defining basic URLs in Rails is really quite simple. Imagine we are building a social web application and we want to be able to accept /users/123 to display the user’s profile page.

To define this route, you could write:

get "users/:id", to: "users#show", as: "profile"  

This will map GET requests that match this URL to the show method on the UsersController.

The sections that are prefixed with a colon, for example :id will be captured and sent to the Controller as parameters.

In this case it allows you to capture the id of the user to find and then pass that id to Active Record like we saw in Querying with Active Record in Ruby on Rails.

I’ve also given this route a name of profile. This allows us to use Rails automatic helpers for generating the URL:

user = User.first

profile_path(user) # /users/123  

By using the the Rails helper methods you can avoid writing out any URLs in your Views. This makes it much easier to change your URL scheme without breaking every existing URL in your application!

Rails will generate the following helper methods for your resource:

  • users_path
  • new_user_path
  • edit_user_path(:id)
  • user_path(:id)

Alternatively you can use the url suffix instead of the path suffix to generate the full URL including the domain and host.

Resource Routing

Whilst you are free to define each individual route of your web application, Rails makes it easier to define all the routes for a given resource in a single definition:

resources :articles  

This will generate the following 7 routes and automatically maps them to Controller actions:

  • GET /articles
  • GET /articles/new
  • POST /articles
  • GET /articles/:id
  • GET /articles/:id/edit
  • PATCH/PUT /articles/:id
  • DELETE /articles/:id

All of these routes will automatically be dispatched to the ArticlesController.

Namespaces

In the example above we created routes for the :articles resource. But if we were building a blog, we would probably want those URLs to be nested under admin and leave the top level free for public URLs.

To accomplish this we can use a namespace:

namespace :admin do  
resources :articles  
end  

This will generate the same 7 routes as before, but this time each will be namespaced under admin and will be dispatched to Admin::ArticlesController.

Nested Resources

When a resource “belongs” to another resource, it often makes sense to nest that resource under it’s parent.

For example, a comment on a blog doesn’t exist in isolation, it exists as part of an article.

To show this hierarchy in the URL scheme, we can create nested resources:

resources :articles  
resources :comments  
end  

Now when Rails generates the comments routes they will automatically be nested under the articles routes.

Conclusion

Defining URLs in Rails is really straightforward. Rails makes it really easy to create a URL scheme for your application that follows the conventions of REST and HTTP.

URLs are an incredibly important part of a web application. URLs should be clear, logical, and allow the application to be traversed without the aid of the user interface.

Whilst URLs can seem like a minor detail in the scope of an entire web application, Rails will keep you on the straight and narrow path of defining a good URL scheme.