#Routing in Rails
##Resources
In Sinatra applications, you may have noticed a pattern in the routes/controller actions (they are the same in Sinatra) you were creating. In Rails, the common routes of index, show, new, edit, create, update, and destroy are all contained in a "resource". You typically will want a resource for each model in your application you want to perform these actions on. For example, this would constitute a users resource:
HTTP verb | Path | Controller Action | Used for |
GET | /users | index | Get a list of all users |
GET | /users/:id | show | Show the profile of a specific user |
GET | /users/new | new | Display a form to create a user |
GET | /users/:id/edit | edit | Display a form to edit a user |
POST | /users | create | Create a new user |
PUT | /users/:id | update | Update an existing user |
DELETE | /users/:id | destroy | Delete an existing user |
This resource would be created with this line of ruby in the config/routes.rb file.
resources :users
It will link the routes, with their appropriate controller actions. In this example, it will assume there is an app/controllers/users_controller.rb file, that contains the index, show, new, edit, create, update, and destroy instance methods inside of a UsersController class.
Sometimes, you don't need all the routes that the resources method will by default create for you. Let's say that the application is going to incorporate the form for creating a user into dropdowns on the main page, and so there is no need for a new route. In that case, use the only option to specify which routes you want:
resources :users, only: [:index, :show, :edit, :create, :update, :destroy]
##Helper Methods
When you create a resource, rails creates a bunch of very handy helper methods that return the path for any given route. These helper methods can be used inside the controller and views instead of having to hardcode in a url for a link.
Path | Helper Method |
/users | users_path |
/users/:id | user_path(:id) |
/users/new | new_photo_path |
/users/:id/edit | edit_photo_path(:id) |
Also, each of these helpers corresponds with another helper, these with _url instead of _path (for example users_url) that return the ENTIRE URL including the host and port along with the path. It would return localhost:3000/users instead of /users.
##Nested Resources
When there is model association going on in an application (which is almost always), nested resources can come into play. Lets say that we want our user model from before to have multiple posts. There are has_many and belongs_to relationships setup in each model, and a migration has been created and ran. What's left is to create the routes necessary to allow a user to view all the posts from a given user, among other things. Rails offers a nifty syntax to automatically generate the routes necessary:
resources :users do
resources :posts
end
This will create these routes:
HTTP verb | Path | Controller Action |
GET | /users/:user_id/posts | index |
GET | /users/:user_id/posts/:id | show |
GET | /users/:user_id/posts/new | new |
GET | /users/:user_id/posts/:id/edit | edit |
POST | /users/:user_id/posts | create |
PUT | /users/:user_id/posts/:id | update |
DELETE | /users/:user_id/posts/:id | destroy |
It will assume there is a PostsController class in the app/controllers/posts_controller.rb file with those actions, just like a normal resource would.
##Collection and Member routes
Sometimes, you may want to add more routes than the 7 provided by default in a resource. You either will want to define a route that will perform an action on the entire collection in the resource (all the users), or on a single member of the resource (an individual user). In order to do this, rails allows for easy implementation of additional routes on members and collections:
resources :users do
member do
get 'preview'
end
collection do
get 'slideshow'
end
end
This will create two additional routes. One will be /users/:id/preview and is our member route. This will map to a preview action in the UsersController. The second route will be /users/slideshow and is the collection route (since you want a slideshow of all users), and is mapped to the slideshow action in the UsersController.