How to Implement Custom Routes for Pages in Rails
This guide gives step by step instructions for how to customize routes in Rails, including how to set the homepage route for an entire application.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

This guide gives step by step instructions for how to customize routes in Rails, including how to set the homepage route for an entire application.

Since this section is all about data flow in Rails, I want to take something of a side step from working on our portfolios, and talk about custom routing because, as I mentioned before, routing is the first step that happens when someone is interacting with your website. They can't get to a controller or database unless they get to a page on your website. That's just logical.

For example, if a user goes to pages/home, that's when the associated pages_controller home method will be triggered. The method will run, and the data will render and be displayed to the user.

Routes.rb

The routes.rb file is a very good place to start when it comes to understanding data flow in Rails.

Rails.application.routes.draw do
  resources :portfolios

  get 'pages/home'

  get 'pages/about'

  get 'pages/contact'

  resources :blogs
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

We’ve discussed how resources are used for scaffolds and for when we are building any CRUD based service. Explicitly, creating, reading, and updating, are all a good fit for resources. For static pages, resources would make no sense, and this is why we have routes like

  get 'pages/home'
  get ‘pages/about’
  get ‘pages/contact'

By default, Rails creates the above routes for us, but those might not always be what routes we want to use. Fortunately, Rails gives us a lot of flexibility, so let's talk about how we can customize them.

Setting the Root Path

For example, with the current route you have to go to /pages/home to get to the homepage, and that is not very intuitive. I'm going to remove get 'pages/home' and at the very bottom of the method, I'm going add root to: `pages#home`

Rails.application.routes.draw do
  resources :portfolios

  get 'pages/about'

  get 'pages/contact'

  resources :blogs
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: 'pages#home'
end

This root to: is setting something called the root path. It is the root of the application, which means, it is your home page. I am going to set the root to pages#home which means the system will look at this and identify pages#home as the homepage for the application and it is going to point to home as the specific controller action. This doesn't have to be called home. This could be named anything we wanted to when we created it. Since I gave it this name when I first created it, we will proceed with that.

To see if this is working, head to the terminal and use the imperative rails s to start the rails server. One thing to note: every time you make changes to your routes, you have to restart your rails server. If I had the rails server going already, I'll have to quit it and then start it again. Otherwise, this route change will not be picked up by the server. Go to your Google Chrome browser and type, localhost:3000. Before this displayed the Yay! You’re on rails page. That was fine but now the root is our home page.

large

So, we are directed to the right page that has our blog posts and skills. Since this is working, we don't have to go to localhost:3000/pages/home anymore. In fact, if you go to this URL, it'll throw an error because that route doesn't exist anymore.

Customizing our Routes

Now that we have our home page set as our root, what about about the other static pages like contact and about?

Instead of going to "localhost:3000/pages/about", I want the ability to just go to "localhost:3000/about". Though it will throw an error if we try it right now, I think it is the most intuitive roughing scheme. To implement this in your routes file the first thing you need to do is remove the word pages in front of the about. Next, I want to point about to pages#about.

- get ‘pages/about'
+ get 'about', to: 'pages#about'

If you remember the output of rake routes, on the far right is Controller#Action column. The mapping has the controller on the left hand side of the hash while the action is on the right. That's the same process we'll follow here.

Rails is smart enough to know that if you pass a get, by itself and you do not pass to to it, that the word on the left side is the controller and the one on the right is the action. That’s just part of the built in Rails magic that is occurring behind the scenes. But, in reality, routes are going to look more like this, get 'about', to: ‘pages#about' where we are declaring them and then mapping them with the controller on the left side of the hash and the action on the right.
Let's make this change for contact as well.

- get ‘pages/contact'
+ get 'contact', to: 'pages#contact'

Developers note: You can use command shift + D to duplicate the line containing your new route. Next hold down the command while you double click on the word about. This will select them both so you can update them at the same time by changing them to contact.

Rails.application.routes.draw do
  resources :portfolios

  get ‘about', to: 'pages#about'
  get 'contact', to: 'pages#contact'

  resources :blogs

  root to: 'pages#home'
end

Save your file and then go to the terminal and run rake routes. We can verify if our changes worked before we go to the browser to test them.

large

Before we had pages in our route and you had to go there to access these other pages. Now we should just see contact and about in our routes.
It's really opportune that you can customize routes with Rails instead of having to use the defaults.

Let's restart the server (because you have to do that each time you change your routes). Even when everything looks like it is going to work correctly you still want to test it in the browser. This is because sometimes little bugs pop up. Type "localhost:3000/about", and you'll see:

large

Likewise, contact is also working.

large

Making a Route Completely Custom

Before we end, I want to show you how to create something completely custom. For example, what happens if we want to change about to about-me ? Because this is a portfolio site using ‘about-me’ makes a lot of sense. However, we do not have an action that is named ‘about-me’. Well, we can pass that name, even if we don't have an action by the same name. This is another helpful thing about Rails. For example, I can even pass something like this:

  get ‘about-me‘, to: 'pages#about'
  get 'asdfasdf', to: ‘pages#contact'

And it'll work.

Restart the server and type "localhost:3000/asdfasdf", and you will now see that it is mapped to the ‘contact’ page, just as about-me is mapped to the ‘about’ page.

large

So, we have complete control to customize our routes. Let's revert back to the original code so that our contact page is mapped to contact!

Last, let’s go to the terminal and take care of our version control. With a git status we will see that the only file we changed was our routes.rb. Let’s go ahead and add that to the git file with git add . We will then commit our changes with a message using git commit -m ‘Configured custom routes for pages’ and finish with git push origin portfolio-feature.

Go to PivotalTracker and if you see, we didn't create a custom route for our portfolio, but we did it for our pages. So, let's add that task Create custom routes for pages and check it as complete.
In the next guide, we'll see how to create custom routes for portfolio items and actually override the routes provided by resources.

Resources