Amr Noman
Amr Noman

Reputation: 2637

How to provide a route for current user in a REST API?

So I have a simple users resource defined in my routes.

resources :users

I need to provide a route so that a logged in user can get his information in the front end. I thought about doing this:

resources :users do
  get 'current' , on: :collection
end

But this semantically means that the route gives a list of current users, not the current user. And Indeed if I do rake routes, it shows the path prefix as: current_users

I can work around the path prefix by doing something like this:

get '/users/current' => 'users#current', as: 'current_user'

But this still looks like it provides a list of users. So, I was wondering if there was a 'right way' to do this kind of thing and how to do it in rails? Or am I thinking too much about this and what I have is fine?

Upvotes: 4

Views: 2263

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

if there was a 'right way'

The "right" way is to use a singular resource:

#config/routes.rb
resource :user #-> url.com/user -> users#show

Of course, the "right" way implies there is a "wrong" way, which is not the case.

Programming is one of the few practices where you can do whatever you want, so long as the result is achieved. Of course, how you achieve that result can be criticized; ultimately, there are a myriad of ways to achieve it...

#config/routes.rb
resources :users do
  get :current, on: :collection #-> url.com/users/current -> users#current
end

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def current
      @user = current_user
   end
end 

The above (your code) does what my code does, just in a different way.

Just because you're using a collection route, doesn't mean you need to pass a collection. The "collection" route is mainly for Rails routing structures; the routes have no bearing on your backend code.

--

This also means you should be willing to experiment with options / switches to customize your routing:

#config/routes.rb
resource :user, path: "current_user", as: :current_user #-> url.com/current_user -> users#show

Upvotes: 5

Todd Knarr
Todd Knarr

Reputation: 1265

Singular Resources as henb noted are what you're looking for. Or this:

get 'user/current' => 'users#current', as :current_user

One thing I've done is use the singular form in the resources statement because the actions dealt with individual users (eg. /usr/573 to display the information for user 573), then added an extra match for the list of all users:

match 'users' => 'user#index', as :user_list, via: [ :get, :post ]
get 'user/current' => 'user#current', as :current_user
resources :user, except: :index

Not precisely RESTful, but it made the URLs reflect accurately whether I was dealing with the set of users vs. an individual user. The :post for the user list is for the search box submission.

Upvotes: 1

henb
henb

Reputation: 577

2.5 Singular Resources Sometimes, you have a resource that clients always look up without referencing an ID. For example, you would like /profile to always show the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action: http://guides.rubyonrails.org/routing.html#singular-resources

maybe you meant it?

resource :user

Upvotes: 2

Related Questions