296

What is the difference between collection routes and member routes in Rails?

For example,

resources :photos do
  member do
    get :preview
  end
end

versus

resources :photos do
  collection do
    get :search
  end
end

I don't understand.

ExiRe
  • 4,727
  • 7
  • 47
  • 92
never_had_a_name
  • 90,630
  • 105
  • 267
  • 383

5 Answers5

443

A member route will require an ID, because it acts on a member. A collection route doesn't because it acts on a collection of objects. Preview is an example of a member route, because it acts on (and displays) a single object. Search is an example of a collection route, because it acts on (and displays) a collection of objects.

Theo
  • 131,503
  • 21
  • 160
  • 205
  • What about the create action? Say I wanted to make an alternative to 'create' - would it count as a member? – digitalWestie Apr 13 '11 at 13:46
  • 1
    Yes, create is a member action. – Theo Apr 13 '11 at 20:03
  • 1
    But what about adding a "get" without any block? Is it member or collection route? My test showed its collection but with different id variable name. – lzap Apr 19 '11 at 15:12
  • 6
    Are you sure about create being a member action. There is no ID to pass. – George Shaw Nov 21 '13 at 05:42
  • @GeorgeShaw The Id u're wondering about will be nested in the url u are sending to the create-action. Let's say that u have a resources called 'posts' and u've a member called 'vote' nested inside resources :posts; of course. Then u wanna create something like a vote; u wanna a vote on a certain post. U'll be sending to the create-action of vote something like this: 'posts/:id/vote'; comprende? and there u've yr ID u're wondering about :) I hope this helps...(...) – YoniGeek Feb 20 '14 at 14:41
  • 6
    @YoniGeek. Not correct. See http://guides.rubyonrails.org/routing.html, 2.7 Nested Resources. Create is always a collection action as you are adding to the collection. Note that the named create path is always plural. In your example you are adding a new vote to the collection of votes that belong to a member of posts. The id refers to the member post, not the collection of votes being created.The named path would be posts_votes_url, for example. – George Shaw Feb 21 '14 at 06:10
  • @Theo How to give action to the given member/collection of resource. I didn't find on net. Although I can ask it as separate question but I think one will get the answer from the comment section... so. please. – zeal Aug 24 '14 at 22:02
  • @zeal This is three years late, but the action is given after the verb. In the examples above, the actions would be "preview" and "search". – furman87 Jul 21 '17 at 12:47
237
                URL                 Helper                      Description
----------------------------------------------------------------------------------------------------------------------------------
member          /photos/1/preview   preview_photo_path(photo)   Acts on a specific resource so required id (preview specific photo)
collection      /photos/search      search_photos_path          Acts on collection of resources(display all photos)
Amit Patel
  • 15,609
  • 18
  • 68
  • 106
  • 2
    Should use `search_photos_path` instead of `search_photos_url` so people won't think `_path` and `_url` are a difference between the two. – Joshua Pinter Jul 14 '16 at 03:51
35

Theo's answer is correct. For documentation's sake, I'd like to also note that the two will generate different path helpers.

member {get 'preview'} will generate:

preview_photo_path(@photo) # /photos/1/preview

collection {get 'search'} will generate:

search_photos_path # /photos/search

Note plurality!

tybro0103
  • 48,327
  • 33
  • 144
  • 170
15

1) :collection - Add named routes for other actions that operate on the collection. Takes a hash of #{action} => #{method}, where method is :get/:post/:put/:delete, an array of any of the previous, or :any if the method does not matter. These routes map to a URL like /users/customers_list, with a route of customers_list_users_url.

map.resources :users, :collection => { :customers_list=> :get }

2) :member - Same as :collection, but for actions that operate on a specific member.

map.resources :users, :member => { :inactive=> :post }

it treated as /users/1;inactive=> [:action => 'inactive', :id => 1]

Nithin
  • 3,679
  • 3
  • 30
  • 55
Beena Shetty
  • 3,676
  • 2
  • 28
  • 31
1

Short Answer:

Both the member and collection blocks allow you to define additional routes for your resources than the seven standard routes that Rails will generate for you.

  • A member block creates new routes on a single member of the resource.
  • A collection block creates new routes for a collection of that resource.

Long Answer

Rails provides the member and 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 article resource.

resources :articles

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 ArticlesController itself.

Custom Member Routes

Here's how you define the preview route on the ArticlesController using the member block.

resources :articles do
  member do
    get 'preview'
  end
end

It 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 preview_article_path and preview_article_url helpers.

➜ 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 :on option.

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:

  1. The article's id is available as params[:article_id] instead of params[:id].
  2. The route helpers changes from preview_article_path to article_preview_path and preview_article_url to article_preview_url.

Custom Collection Routes

To add a new route for the collection of a resource, use the collection block.

resources :articles do
  collection do
    get 'search'
  end
end

This adds the following new route. It will also add a search_articles_path and search_articles_url helper.

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.

Conclusion

Rails allows you to break out of its convention of using seven resourceful routes using the member and collection blocks. Both allow you to define additional routes for your resources than the standard seven routes.

A member block acts on a single member of the resource, whereas a collection operates on a collection of that resource.

Source: Define New Routes Using the Member and Collection Blocks

software_writer
  • 3,941
  • 9
  • 38
  • 64