- Read Tutorial
- Watch Guide Video
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.
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.
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:
Likewise, contact
is also working.
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.
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.