Routes in Rails Explained

I am about 2 weeks into learning Ruby on Rails now, so I thought it would be useful to write a post which explains something really fundamental and important to understand - how to route a Rails application :D

It is something that took me a while to get my head around because in Rails there are a lot of interconnected dependencies and if you don't understand how everything is connected then it is hard not to get lost. To understand how routes work you need to understand how the different parts (of the MVC... read previous blog post for an explanation!) are connected and thus how data is coming into and travelling around the application.

So quickly... what are routes??

Routes are used to recognise a URL and send that information to your controller. They are also used to specify where information will be outputted on the web (aka the URL it will be viewed upon).

Now there is only so much detail I can go into about the structure of a Rails app in a blog post, there are of course whole books about how to build Rails applications and pages and pages of documentation available. Rails guides http://guides.rubyonrails.org/ provides an extensive and extremely useful resource for learning Rails development. That being said, I have found that sometimes being presented with such vast quantities of information can be quite overwhelming and the underlying stress kicks in thinking “oh god so much to learn” and then the information doesn't really go in... and I end up frantically reading the same paragraph 5 times and forgetting what I just read each time.

So to try and prevent that a bit for others, in this post I am going to explain Rails routing in a way that I have been able to break it down to and understand after just a few weeks. It will probably still be quite long... but written in a more 'friendly way'. Hopefully after reading this, when you do move on to the more extensive guides you will be less freaked out. This info is based on my experience after working on authenticating a Rails application which displays online workshops to the user, reading online, learning from my boss Ali and a session at Codebar (i'll write all about Codebar in another post... but for now check out codebar.io to learn more) with Camille who was my coach for the session, taking me through how Rails functions.

From the beginning...

A Rails app is structured in a specific way. This just means that when you generate a new Rails project it will create a project file structure... so basically lots of folders with predefined names containing files for you to write code in to.

Here is a list of files at the top level directory for the application i've been working on, which is an app that a user can sign into and then complete online workshops:

Image

Inside the /app directory you will find the directories which designate where you need to write code for your models, views and controllers:

Image

So this is the very tip of the iceberg of what I was saying earlier about different parts of of the Rails app relying on other parts to make stuff happen. To keep everything organised and for certain inbuilt functionality to automatically 'just work' the anatomy of the program structure needs to be very specific.

The files containing your code also need to be named in a certain way. This has a knock on effect on how the route will be specified and thus what the URL will be to navigate to your web page. 'Named in a certain way' basically means that when naming files you will need to use plurals in some places and not in others.

I'll demonstrate this with examples from my 'users' MVC which is used for things such as creating a new user when they sign up to use the application.

The name of a controller should be: Plural

Therefore it is called: Users_Controller.rb

and can be found in: app/controllers/users_controller.rb

Name of the View: The directory name will be the same as the controller name aka plural. The file (that you write the view code in) will begin with the name of the controller action you are generating the view for.

So the name of the view that I want to generate for the new method for my Users_Controller (shown below):

Image

Is: users/new.html.haml (found in app/views/users/new.html.haml)

The name of the model is singular. So the file is called user.rb and the class is called User:

Image

It can be found in: app/models/user.rb

The database table name will be plural

create_users (found in config/db/migrate):

Image

So why am I going on so much about plurals... not overly exciting... but firstly I wanted to re-enforce the importance of the MVC being set up in a specific way and secondly the use of plurals makes a difference in setting up the routes for a project. Here are the routes for the project I have been working on:

Image

Routes are specified in config/routes.rb

So as you can see they are all plural except for session. Why is this? It's just a case of thinking logically/verbosely. There are going to be multiple users using this web app so 'users' is chosen but these users will only be logging in for their individual workshop session... 'lets start a new sessions' doesn't really make sense. Hence we use session.

To start understanding how routes work let's have a look at the first route that is being set up in the first line of the code block:

Image

So what will be the outcome of this line of code... why is it there? Well this is the bit of code that will generate what the URL that the user navigates to will be called. So to view the 'Sign up' form I want the user to go to:

www.nameofwebsite/users/new

or if it helps to visualise from a development point of view... viewing locally:

http://localhost:3000/users/new

When the user goes to this URL the route will tell the controller... "look someone has activated /users (name of controller) /new (name of method to call)". Then the new method will be called in the controller and thus the info will be passed around the MVC; and in this case the very beautiful Sign up form that I have been making will appear for the user to fill out and submit.

So now we know the outcome of this line of code, lets go back to breaking down how it happens.

It starts with the word resources.Why? Well Rails uses something called 'resourceful routes' in order to generate URLs. This is the preferred way to generate routes, you can also use something called 'the match method' but I have no idea how that works... so we will stick with this.

To understand this we need to know a little about resources on the web. When a user navigates to a page it sends a request to Rails using a HTTP method.

HTTP methods are: GET, HEAD, POST, PATCH, PUT, TRACE, OPTIONS, CONNECT and DELETE.

HTTP requests will probably fill up another blog post, but really the ones you need to know are:

GET – Gets information from the server

POST – Sends information to the server

DELETE – Deletes the resource

So when Rails receives a HTTP request it performs an operation on a resource. What is a resource? A resource is the first thing we are defining in our line of code:

user route

Alhough it is kind of confusingly called 'resources' because of the whole plural convention I was explaining earlier. Here we have defined that the resource we want to perform our HTTP request on is :users aka the users_controller. I have specified inside the users_controller that it makes use of an inbuilt ruby feature called `params` which is used to pass HTTP data into the Rails program. In my users_controller I have defined a user_params method containing this params method. I then pass this into other methods to make use of the relevant pieces of data that the user has entered for example their name, email address and password.

user params method

In the second part of the code defining the first route we have only: [:new, :create] which is a ruby hash. This is where we specify which actions we want to generate routes for. We do this because automatically Rails will generate routes for all 7 actions (I will talk about what ‘actions’ are in a moment) they are called index, show, new, create, edit and update. The stuff that actually happens through the use of the new and create actions are specified as methods inside my users_controller. Therefore they are the only actions I need hence the use of filtering with ‘only’.

This is where it may start to get confusing because if a user tried to navigate to localhost:3000/users/create they wouldn't come to a URL address at which a page would be rendered.

To understand this you need to go into the terminal, navigate to the project directory you are working on and run the command `rake routes`:

rake routes

A quick note on what prefix is – In the prefix column we see a list of 'helpers' that the routes have generated. These are useful because in other parts of your program you don't have to use a hardcoded URL string. So for example the URL that renders the 'sign in' page has the prefix new_session. I want to direct the user here once they have successfully filled in the registration form. I therefore use two helper methods, the second being the prefix/helper shown when we run rake routes:

prefix example

Looking at the next 3 columns, I can continue to explain why navigating to localhost:3000/users/new will render a page, but navigating to localhost:3000/users/create will not, even though I specified in the controller that routes would be generated for both of these actions using only: [:new, :create].

The verb specifies the HTTP request that is being received. The URI pattern specifies the URL associated with each action which is specified in the final column Controller#Action. This points to the name of the controller and method within it to call.

These method names are associated with HTTP methods, so when designing a web application you need to be mindful about what you want to happen. There are matched up like so:

HTTP - Action

GET – index

GET – new

POST – create

GET – show

GET – edit

PATCH/PUT – update

DELETE - destroy

The URI pattern for /users/new has the verb: GET. It renders a view because it is getting information and displaying it to the user. For this reason this application has been set up to render a view when this happens.

The URI pattern for /users/create has the verb: POST. The purpose of this action in this case is to take the data that the user has entered into a form and save it to the database. We don't need a view to be generated for this so instead the user is redirected to another URL. As a rule of thumb we never use a view (view is the thing that renders the webpage in a browser) for POST or DELETE HTTP requests.

I will end with shedding a little more light on the URI names.

Firstly. what does the (.:format) part mean after /users/(.:format)?

Generally you can ignore it and pretend it isn't there. But it's use is that it allows you to add certain formats on to the end of the URL. The web standard is HTML so it is not explicitly specified. But you could for instance add .json to the end of the URL which, if whoever made the site has created a view which renders in .json format, you would be able to see that instead.

In some of the URI patterns you will be able to see they contain /:id:

id example

In this example the reason is that there are multiple workshops available for the user to work through. The application has been set up so that when the user navigates to a specific exercise, the URL will change depending on the name of exercise and which number exercise they are working on:

www.nameofwebsite.com/workshops/nameofworkshop/exercises/exercisenumber

From the controller#action column shown when we ran rake routes, we can see that the place which specifies how the app gets the names of the :workshop_id and :id to fill in the :id parts of the URL happens to be the show method in the exercises_controller. I won’t go in to too much detail about this but in exercises_controller params (ruby method that recognises http data) is again used:

params ex