:as lets you customize your route helpers

Simply put, you can use the :as option in your routes.rb file and customize or override your route helpers. But before we dive into :as, let’s make sure we know what routes are and what route helpers do.

Quick overview: routes and route helpers

Lets say we have a class Student and a table students, they all follow REST conventions perfectly because we were used #resources in our routes file:

resources :students

When I do rake routes in my console, these are all the routes that Rails has so kindly created for me:

~/Coding/stdnt-example$ rake routes Prefix Verb URI Pattern Controller#Action

students GET /students(.:format) students#index

POST /students(.:format) students#create

new_student GET /students/new(.:format) students#new

edit_student GET /students/:id/edit(.:format) students#edit

student GET /students/:id(.:format) students#show

PATCH /students/:id(.:format) students#update

PUT /students/:id(.:format) students#update

DELETE /students/:id(.:format) students#destroy

Magical. If you aren’t familiar with these 4 columns, we’re mainly concerned with the 1st, “Prefix”, and 3rd, “URI Pattern”. We use route helpers based off the prefix, and then they take us to the page at the URI. Route helpers are these guys:

student_path(@student)

which replace this ugliness :

“/students/#{@student.id}”

Where did we get that route helper? All we did was add “_path” to the prefix. That’s it. In that table the prefix “student” is associated with the /students/:id page. If we wanted to use a route helper to get to /students , it would just be students_path .

Route helpers are the friendlier, DRYer, safer way of writing path names in your code. You should use them. A lot.

Custom routes when Resources isn’t enough

The resources method is great, but it can’t cover everything. Custom routes still need to be put in manually. Let’s say we want a special page that showed the a student’s best grades from all their classes, a top score page for the nerds, if you will. That would not fall under #resources’ auto generated routes, we would have to make a custom one:

# routes.rb

get '/students/:id/grades', to: 'students#grades'

But now when we run rake routes , we get this:

Prefix Verb URI Pattern Controller#Action

students GET /students(.:format) students#index

POST /students(.:format) students#create

new_student GET /students/new(.:format) students#new

edit_student GET /students/:id/edit(.:format) students#edit

student GET /students/:id(.:format) students#show

PATCH /students/:id(.:format) students#update

PUT /students/:id(.:format) students#update

DELETE /students/:id(.:format) students#destroy

GET /students/:id/grades(.:format) students#grades

Lame. That dynamic routing means Rails doesn’t know how to autogenerate a prefix. It works just fine without one, users can still navigate to it, but this means we’re going to have to type out this monstrosity every time we work with it in our code:

“/students/#{@student.id}/grades”

The whole point of Rails is to have code magically be written for you. If rails is normally David Copperfield making the Statue of Liberty disappear, then a page with no route helper is like your 7 year old cousin asking you to pick a card. Terrible.

Instead, lets use :as to get a custom route helper!

get '/students/:id/grades', to: 'students#grades', as: 'grades'

which gives us this prefix:

Prefix Verb URI Pattern Controller#Action # ...those old routes still

grades GET /students/:id/grades(.:format) students#grades

Overriding presets

It’s also possible to create a route helper that doesn’t go with convention. Suppose we have a page for new students to get accounts, /students/new , but also a page with info for new students, /new-students . This is a contrived example but whatever, the point is, you have two similar sounding URI’s because life isn’t fair. So, since students/new is really more of a registration page, lets avoid confusion and make a route helper that does that:

# these 3 lines are in our routes.rb file resources :students

get '/students/new', to: 'students#new', as: 'register'

get '/new-students', to: 'students#new_students,'

# ...which gives us these routes:

Prefix Verb URI Pattern Controller#Action

students GET /students students#index

POST /students students#create

new_student GET /students/new students#new

edit_student GET /students/:id/edit students#edit

student GET /students/:id students#show

PATCH /students/:id students#update

PUT /students/:id students#update

DELETE /students/:id students#destroy

register GET /students/new students#new

new_students GET /new-students students#new_students

Now instead of confusing new_student_path with new_students_path , we simply use register_path and new_students_path instead.

Shorter custom routes

Rails knows how to generate rails helpers for non dynamic routes, but sometimes we want something shorter. Take this path, which shows the best students of the top region:

get '/students/region-1/top-20', to: 'students#tops'

Rails automatically makes a route helper: students_region_1_top_20_path . Gross. Instead of typing that long thing out, let’s essentially alias our route:

get '/students/region-1/top-20', to: 'students#tops', as: "r1_top20"

Now the route helper is just r1_top20_path .

That’s the basics!

For most basic sites, #resources and Rails itself will take care of routing and route helpers for you. But it is always good to understand how to customize and do things manually. Also, :as has some other uses that are described in the Rails Docs that deal with scope and nesting, so I recommend the curious go check it out. I hope this helped, as always, don’t hesitate to ask any questions or point out confusing/wrong parts if you find them.

Happy coding everyone,

Mike