Deviseのルーティングが微妙なのでgemを作ってみた
Devise便利ですよね。簡単にリッチな認証機能がつくれます。
# config/routes.rb devise_for :users
new_user_session GET /users/sign_in(.:format) devise/sessions#new user_session POST /users/sign_in(.:format) devise/sessions#create destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroy user_password POST /users/password(.:format) devise/passwords#create new_user_password GET /users/password/new(.:format) devise/passwords#new edit_user_password GET /users/password/edit(.:format) devise/passwords#edit PUT /users/password(.:format) devise/passwords#update cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy user_confirmation POST /users/confirmation(.:format) devise/confirmations#create new_user_confirmation GET /users/confirmation/new(.:format) devise/confirmations#new GET /users/confirmation(.:format) devise/confirmations#show
いまいちなところ
Devise::RegistrationsControllerの役割があいまい
/users
が Devise::RegistrationsController に取られてるのはひどい。普通 UsersController になるはずでしょう。
(PUT /users
やDELETE /users
も地味にひどい)
さらにここによく使うresources :users
を足すとカオスに…。
cancel_user_registration GET /users/cancel(.:format) devise/registrations#cancel user_registration POST /users(.:format) devise/registrations#create new_user_registration GET /users/sign_up(.:format) devise/registrations#new edit_user_registration GET /users/edit(.:format) devise/registrations#edit PUT /users(.:format) devise/registrations#update DELETE /users(.:format) devise/registrations#destroy users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy
何をどう使えばいいんでしょうか、これ…。
何が問題なのか
- 複数形である
users
は普通「ユーザー全体」をさすはず(コレクションリソース)。なのに registrations#update は「自分自身を更新」つまり「自分自身」をさしている。 #cancel, #edit, #destroy も同様 - そもそもURLにも出てこない“registrations”っていったい何?
「自分自身」をさすリソースは1つしかないので単数形で表現できます。
resource :user # (a)単数 resources :users # (b)複数 resource :users # (c)まぎらわしいのでよくない
(a)と(b)は別のリソースなので区別しましょう。
解決策(案)
devise-better_routes gemを使うと、ルーティングはこのようになります。
# Gemfile gem 'devise-better_routes'
users POST /users(.:format) users#create new_user GET /users/new(.:format) users#new cancel_current_user GET /current_user/cancel(.:format) current_users#cancel edit_current_user GET /current_user/edit(.:format) current_users#edit current_user PATCH /current_user(.:format) current_users#update PUT /current_user(.:format) current_users#update DELETE /current_user(.:format) current_users#destroy
謎のregistrationsは消えて、コントローラがusersとcurrent_usersに整理されました。
このコントローラは用意されていませんが、基本は単にこんな感じで作ってやればOKです。
# app/controllers/users_controller.rb class UsersController < Devise::RegistrationsController end # app/controllers/current_users_controller.rb class CurrentUsersController < Devise::RegistrationsController end
同様に、passwordとsessionもパスが変更されます。
オプション
/current_user
って名前はいまいち…、というときは、オプションで変更することができます。
# config/routes.rb devise_for :users, path_names: {current_user: 'me'}
users POST /users(.:format) users#create new_user GET /users/new(.:format) users#new cancel_me GET /me/cancel(.:format) me#cancel edit_me GET /me/edit(.:format) me#edit me PATCH /me(.:format) me#update PUT /me(.:format) me#update DELETE /me(.:format) me#destroy
いい感じじゃないですか?
Deviseへissueを投げてみた
Thanks for the proposal. Yes, it make sense, even though we have originally decided to not pollute two namespaces for the same Devise controller. Unfortunately, this is a very backwards incompatible change, so any change of this dimension would have to wait until Devise 4.0 (and we just released 3.0). Fortunately, you can customize it on your own, as you did. :)
So I am closing this but leaving a note to myself that we could possibly revisit this (in a year or two).
Registration routes are confusing · Issue #2505 · plataformatec/devise · GitHub
ってことで、リップサービスかもしれないけどDevise 4.0に期待w