Reputation: 93306
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.
Upvotes: 298
Views: 111827
Reputation: 4488
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.
member
block creates new routes on a single member of the resource.collection
block creates new routes for a collection of that resource.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.
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:
params[:article_id]
instead of params[:id]
.preview_article_path
to article_preview_path
and preview_article_url
to article_preview_url
.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.
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
Upvotes: 3
Reputation: 15985
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)
Upvotes: 239
Reputation: 3736
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]
Upvotes: 15
Reputation: 49743
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!
Upvotes: 36
Reputation: 132972
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.
Upvotes: 446