46

What is the logical difference between resource and resources methods

Here is some examples:

resource :orders, :only => [:index, :create, :show]

> rake routes
 orders POST       /orders(.:format)            orders#create
        GET        /orders(.:format)            orders#show


resources :orders, :only => [:index, :create, :show]

> rake routes
 orders GET        /orders(.:format)            orders#index
        POST       /orders(.:format)            orders#create
  order GET        /orders/:id(.:format)        orders#show


resource :orders

> rake routes
     orders POST       /orders(.:format)            orders#create
 new_orders GET        /orders/new(.:format)        orders#new
edit_orders GET        /orders/edit(.:format)       orders#edit
            GET        /orders(.:format)            orders#show
            PUT        /orders(.:format)            orders#update
            DELETE     /orders(.:format)            orders#destroy


resources :orders

> rake routes
     orders GET        /orders(.:format)            orders#index
            POST       /orders(.:format)            orders#create
  new_order GET        /orders/new(.:format)        orders#new
 edit_order GET        /orders/:id/edit(.:format)   orders#edit
      order GET        /orders/:id(.:format)        orders#show
            PUT        /orders/:id(.:format)        orders#update
            DELETE     /orders/:id(.:format)        orders#destroy

It looks like method resource does not create route for index, and helpers in some cases are different (new_order and new_orders). Why?

alexkv
  • 5,144
  • 2
  • 21
  • 18

2 Answers2

97

At a high level, the intent of resource is to declare that only one of these resources will ever exist. For example:

resource :profile, :only => [:edit, :update]

As a user, I should only be able to update my own profile. I should never be able to edit other users' profiles, so there's no need for a URL scheme like /users/1/profile/edit. Instead, I use /profile/edit, and the controller knows to use the current user's ID rather than the ID passed in the URL (since there is none).

That's why you don't get an index action with resource: there's only one resource, so there's no sense in "listing" them.

Brandan
  • 14,735
  • 3
  • 56
  • 71
  • Interesting! Thanks for this illuminating explanation. So this means we have profile controller which will be different from a users controller? Also if I want the url to look like `/profile/settings`, I can use `collection { get 'settings' }` – Agent47DarkSoul Nov 05 '13 at 13:47
43

Actually you are right, resource should not create an index action, unless you ask for the index action explicitly, this way:

resource :orders, :only => [:index, :create, :show]

Helpers should differ too, but not that much as in your example, because the convention is to use a singular form with the resource method, and the plural with the resources

resources :orders
=> rake routes

     orders GET        /orders(.:format)            orders#index
            POST       /orders(.:format)            orders#create
  new_order GET        /orders/new(.:format)        orders#new
 edit_order GET        /orders/:id/edit(.:format)   orders#edit
      order GET        /orders/:id(.:format)        orders#show
            PUT        /orders/:id(.:format)        orders#update
            DELETE     /orders/:id(.:format)        orders#destroy

resource :order
=> rake routes
      order POST       /order(.:format)            orders#create
  new_order GET        /order/new(.:format)        orders#new
 edit_order GET        /order/:id/edit(.:format)   orders#edit
            GET        /order/:id(.:format)        orders#show
            PUT        /order/:id(.:format)        orders#update
            DELETE     /order/:id(.:format)        orders#destroy

And the logical difference is to declare you logically can't have the plural for resource in your app, for example Admin or whatever

Adobe
  • 12,967
  • 10
  • 85
  • 126
alony
  • 10,725
  • 3
  • 39
  • 46
  • 2
    i think you mean the first line to say `resource :orders, :only ...` – Don Cheadle Feb 06 '15 at 15:45
  • "Helpers should differ too": it means that you get `new_order_path` for `resources` and `new_orders_path` for `resource`. – Adobe May 27 '16 at 09:58
  • 1
    The main difference is not just index page. -- **resources** will create routes with index page and also will require :id parameter to edit, update, destroy and show actions ([Check]http://guides.rubyonrails.org/routing.html#specifying-a-controller-to-use) -- **resource** will create the same routes without index route and without required :id param. ([Check] http://guides.rubyonrails.org/routing.html#singular-resources) – stopanko Apr 24 '17 at 15:38