22

Reading this: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

What does it mean to add a 'member route'?

or do add a route to the collection?

What is a member and a collection when talking about routes?

Blankman
  • 259,732
  • 324
  • 769
  • 1,199

2 Answers2

58

They're both ways to add additional actions to a resource-based route in Rails.

  • A member route requires an ID, because it acts on a member.
  • A collection route doesn't require an ID because it acts on a collection of objects.

I like to think of them in terms of RESTful URLs. Consider the basics for a resource/model Foo

GET    /foo            # FooController#index
GET    /foo/:id        # FooController#show
GET    /foo/new        # FooController#new
POST   /foo            # FooController#create
GET    /foo/:id/edit   # FooController#edit
PUT    /foo/:id        # FooController#update
DELETE /foo/:id        # FooController#destroy

Notice how:

  • Some routes have :id placeholders for Foo.id, and so refer to a specific Foo
  • Some routes have no :id, and thus refer to all Foos (and/or no specific foo, as in #new and #create)
  • Some routes (index/create, show/update/destroy) have the same URL, and use HTTP methods to differentiate between them
  • Some routes (edit/show) are basically the same (method & URL prefix) except for a different suffix (including "no suffix") at the end.

Member routes and collection routes let you add additional routes/actions using the same techniques as I listed above.

A member route adds a custom action to a specific instance using the URL suffix and HTTP method you provide. So, if you had a member route declaration of :member => { :bar => :get }. you'd get an additional route of:

GET    /foo/:id/bar # FooController#bar

Note how it overloads GET /foo/:id in the same way that `edit' does. This is how you'd implement a "delete" action that provides a UI for the "destroy" action.

Similarly, a collection route adds an overload to the collection and/or a non-specific instance (it's up to you to decide exactly what it implies). So, if you declared :collection => { :baz => :get }, you'd get an additional route:

GET    /foo/baz        # FooController#baz

...in very much the same way as new.

You can also customize the HTTP method.

For example, I just recently had a project where I needed a "reply" action on a Comment. It's basically the same idea as Comment#create (which uses POST), except that it's in reference to a specific parent Comment. So, I created a member route: :member => { :reply => :post }. This gave me:

POST   /comment/:id/reply   # CommentController#reply

This keeps the routes restful while still expanding upon the basic 7 actions.

Muhammad Ali
  • 2,173
  • 15
  • 20
Craig Walker
  • 49,871
  • 54
  • 152
  • 212
11

The built in member routes are show, edit, update and destroy, since they handle an individual record. index would be a collection route as it returns a collection of records.

So it really depends if you want to do something with a single record (member) or multiple records (collection).

The url helpers reflect singular (member) and plural (collection). For example:

This is a member:

person_path(@person)

This is a collection:

people_path()

If you define a custom collection path, it could look like this in your routes.rb:

resources :people do
  member do
    put :make_manager
  end
  collection do
    get :show_managers
  end
end

To make somebody a manger:

make_manager_person_path(@person)

To list all managers:

show_managers_people_path()

I don't think that the route "cares" if you use it differently, but this is the Rails way. It will make your code easier to read and other coders will have it easier to understand and maintain your code.

Wukerplank
  • 4,156
  • 2
  • 28
  • 45