tbodt
tbodt

Reputation: 16987

Is there a better way to define these routes?

I'm working on supporting users in my Rails app. There's no need for a user to even be aware that there are other users out there. I don't want to just use resources :users, because the routes that generates are these:

      users GET    /users                    users#index
            POST   /users                    users#create
   new_user GET    /users/new                users#new
  edit_user GET    /users/:id/edit           users#edit
       user GET    /users/:id                users#show
            PATCH  /users/:id                users#update
            PUT    /users/:id                users#update
            DELETE /users/:id                users#destroy

(.:format) removed for improved readability.

You'd have to put the user id number in the URL, and that offers a chance for users to be aware that other users exist. I want these routes:

      users GET    /users                    users#index
            POST   /users                    users#create
   new_user GET    /users/new                users#new
  edit_user GET    /users/me/edit            users#edit
       user GET    /users/me                 users#show
            PATCH  /users/me                 users#update
            PUT    /users/me                 users#update
            DELETE /users/me                 users#destroy

Yes. /users/me is the path of your user, and that's the only user path you can get at.

But the problem is defining these routes. Here's one idea:

resources :users, constraints: { id: 'me' }

And in the User model:

def to_param
  'me'
end

But that seems too kludgy for me. Any better ideas?

Upvotes: 0

Views: 195

Answers (1)

Eddie
Eddie

Reputation: 496

With Singular Resources your are good to go ;-)

Define your routes like this:

# config/routes.rb
resources :users, only: [:index, :create, :new]
resource :user, path: '/users/me', only: [:show, :edit, :update, :destroy]

Your routes will be singular (/user) if you leave the path: option. Play around with the options ;-)

And your rake routes result should look like this:

   Prefix Verb   URI Pattern              Controller#Action
    users GET    /users(.:format)         users#index
          POST   /users(.:format)         users#create
 new_user GET    /users/new(.:format)     users#new
edit_user GET    /users/me/edit(.:format) users#edit
     user GET    /users/me(.:format)      users#show
          PATCH  /users/me(.:format)      users#update
          PUT    /users/me(.:format)      users#update
          DELETE /users/me(.:format)      users#destroy

You can also test the routes on the Rails console (rails c)

2.1.3 :001 >  Rails.application.routes.url_helpers.user_path
 => "/users/me" 

2.1.3 :002 >  Rails.application.routes.url_helpers.edit_user_path
=> "/users/me/edit" 


If you want, you can pluralize :user on the Singular Resources, but don't forget to set the as: option, her an example:

# config/routes.rb
resources :users, only: [:index, :create, :new]
resource :users, path: '/users/me', as: 'user', only: [:show, :edit, :update, :destroy]


Please take a look to the notes and warnings in the Rails guide! Here is an excerpt:

A long-standing bug prevents form_for from working automatically with singular resources. ...

Upvotes: 3

Related Questions