Define New Routes Using the Member and Collection Blocks
This post shows how to define new routes using the member and collection blocks provided by the Rails router.
A single call to
resources in the
routes.rb file declares the seven standard routes for your resource. What if you need additional routes? Don't worry. Rails provides the
collection blocks so you can define custom routes for both the resource collection and the individual resource.
Here's how you'd typically define routes for the
This creates the following routes.
➜ bin/rails routes -g article Prefix Verb URI Pattern Controller#Action articles GET /articles(.:format) articles#index POST /articles(.:format) articles#create new_article GET /articles/new(.:format) articles#new edit_article GET /articles/:id/edit(.:format) articles#edit article GET /articles/:id(.:format) articles#show PATCH /articles/:id(.:format) articles#update PUT /articles/:id(.:format) articles#update DELETE /articles/:id(.:format) articles#destroy
But let's say you are writing your articles in markdown, and need to see a preview of the article as you write it.
You could create a
PreviewController and display the article's preview using its
show action, but it's convenient to add a preview action on the
Custom Member Routes
Here's how you define the
preview route on the
ArticlesController using the
resources :articles do member do get 'preview' end end
The Rails router adds a new route that directs the request to
ArticlesController#preview action. The remaining routes remain unchanged. It also passes the article id in
params[:id] and creates the
➜ bin/rails routes -g article Prefix Verb URI Pattern Controller#Action preview_article GET /articles/:id/preview(.:format) articles#preview ...remaining routes
If you have a single
member route, use the short-hand version by passing the
:on option to the route, eliminating the block.
resources :articles do get 'preview', on: :member end
You can go one step further and leave out the
resources :articles do get 'preview' end
It generates the following route.
➜ bin/rails routes -g preview Prefix Verb URI Pattern Controller#Action article_preview GET /articles/:article_id/preview(.:format) articles#preview
There are two important differences here:
- The article's id is available as
- The route helpers changes from
Custom Collection Routes
To add a new route for the collection of a resource, use the
resources :articles do collection do get 'search' end end
This adds the following new route. It will also add a
search_articles GET /articles/search(.:format) articles#search
If you don't need multiple
collection routes, just pass
:on option to the route.
resources :articles do get 'search', on: :collection end
This will add the same route as above.
Rails allows you to break out of its convention of using seven resourceful routes using the
collection blocks. Both allow you to define additional routes for your resources than the standard seven routes.
member block acts on a single member of the resource, whereas a
collection operates on a collection of that resource.
I hope you found this article helpful, and you learned something new. Let me know in the comments below what you think.
Thanks for reading!