Rails Resources
Learning Goals
- Understand what the
resources
syntax inroutes.rb
generates for us. - Understand what nesting
resoures
inroutes.rb
generates for us. - Understand the 5 pieces of information
rake routes
gives us. - Use route helpers
Vocab
- routes
- route helper
WarmUp
In your notebook, without using your computer, fill in the following table for the 8 ReSTful routes for a generic “resource”
Verb | URI Pattern | Controller#Action |
GET | /resources | resources#index |
Rails Resources
Rails gives us a handy shortcut for generating the 8 ReSTful routes in our routes.rb file. Open up any Rails app, such as SetList, and add the following line anywhere in your routes file:
resources :cats
Run rake routes -c cats
from the command line. The -c
stands for controller, so it will only show you routes for the cats.
With a partner, explore what this output gives you.
Only/Except
You never want to create routes that you haven’t implemented in your code. If you have resources :cats
in your routes file, but you haven’t implemented the CatsController#destroy
action, you would be exposing an unused route. Instead, we give our resource an only
option to explicitly say which ReSTful routes we want created. For example, if we only wanted the cats index, new, and create actions, we could put this in our routes file:
resources :cats, only: [:index, :new, :create]
You can also use except
, which will generate the 8 ReSTful routes except the ones specified:
resources :cats, except: [:destroy]
This would be the same as:
resources :cats, only: [:index, :show, :new, :create, :edit, :update]
With a partner, refactor some of the ReSTful routes in SetList to use the resources
syntax.
Nested Resources
Some resources are logically dependent on other resources. In SetList, Songs can’t exist without an Artist.
If we look in our routes for SetList, we’ll see:
get "/artists/:artist_id/songs/new", to: "songs#new"
When we want to make a new song, we need to know which artist we are making the song for. We can also accomplish this with the resources
syntax by nesting with a do
block:
resources :artists do
resources :songs
end
This will generate 8 ReSTful routes for artists and 8 ReSTful routes for songs that are nested under an artist. You can also use only/except for nested resources:
resources :artists, only: [:show] do
resources :songs, only: [:edit]
end
Just like before, we only want to create the routes we need.
With a partner, refactor the nested routes in SetList to use the resources
sytnax.
Route Helpers
If you run rake routes
, you’ll notice the first column is called “prefix”. Rails will use the “prefix” column to build route helpers.
Route helpers will generate a path for you (note: just the path, not the VERB). All you have to do is append _path
to the end of the prefix name. For example, if you have this in your routes:
resources :cats, only: [:index]
Then rake routes -c cats
should give you:
Prefix Verb URI Pattern Controller#Action
cats GET /cats(.:format) cats#index
Using that prefix cats
, we can use cats_path
anywhere in our Rails app to generate the path /cats
.
Generally, any row in your rake routes
output that does not include a prefix uses the same prefix as the line above it.
Passing Parameters to Route Helpers
Some paths include parameters. For example:
resources :cats, only: [:show]
Gives you this rake routes
output:
Prefix Verb URI Pattern Controller#Action
cat GET /cats/:id(.:format) cats#show
You can’t generate the path using cat_path
because it is expecting an :id
. Any time a route helper needs a dynamic parameter, like :id
we MUST pass a value to the route helper. For example cat_path(29)
will generate /cats/29
.
We can also pass an object rather than the actual value of the parameter and Rails is smart enough to extract that object’s id. This is considered best practice:
journey = Artist.create(name: 'Journey')
visit artist_path(journey)
Be careful. If you forget to pass a parameter to a route helper that needs it, the error message will start to look like a “missing route” error. Read the ENTIRE error, and it will actually tell you that the route helper is missing a parameter.
Partner Practice
Refactor some of the code in setlist to use Route Helpers rather than hardcoded routes.
Checks for Understanding
- What are the 8 ReSTful routes and their controller/actions?
- What routes would
resources :dogs, only: [:destroy, :index]
generate? - What routes would the following generate?
resources :owners, only: [:index] do
resources :dogs, only: [:show]
end
- Why should you use
only
/except
? - How can you use the prefix column from
rake routes
?