p4dハッカソン成果

Rails Gems realize RESTful modeling patterns

Rails Gems realize RESTful modeling patterns

ユーザー認証のGemのはなし

Session Resourceパターン

PUT(POST) /session
DELETE    /session

認証のセッション自体をリソースととらえる。
Railsでいう「モデル」ではないリソースの典型例。

http://rest-pattern.hatenablog.com/entry/session-resource

Deviseの場合

つかいかた

generatorでモデル生成

rails g devise User

コントローラ、ビューはあらかじめ用意されている(継承してカスタマイズ可能)

  • Devise::SessionsController
  • Devise::RegistrationsController
  • Devise::PasswordsController
  • Devise::ConfirmationsController

など
ルーティングも生成される。

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 /usersDELETE /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
user_cancel GET /users/:user_id/cancel(.:format) users#cancel
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

内部的にはresourceでの指定なのになぜかパス名が複数形/usersのようにつく。

resource :registration, options do
  get :cancel
end
何がまずいのか
resource  :user  # (a)単数
resources :users # (b)複数
resource  :users # (c)まぎらわしいのでよくない

(a)と(b)は別のリソースなので区別しましょう。

ユーザーのリソース/users, /users/:idと、自分自身をさすリソースの両方が必要なとき、どうしますか?

  1. ユーザーのリソースで代用する

自分のidで/users/:id

  1. (a)と(b)を両方つくる

  2. ??

解決策

Deviseのパスに単数形もしくは'my'を指定する(Private Resourceパターン)。
RegistrationsControllerは使わない。

devise_for :users, path: 'user', skip: :registrations
devise_scope :user do
  resource  :user
  resources :users # 必要なら
end

class UsersController < Devise::RegistrationsController
  …
end

これをもっと簡単に書けるようにします。…(予定)

collectionとnamespaceの混同問題

Authlogicの場合

専用のgeneratorはない。モデルAuthlogic::Session::Base(ActiveRecordではないモデル)を用意している。

class Session < Authlogic::Session::Base
end
class User < ActiveRecord::Base
  acts_as_authentic
end

SessionsControllerを普通に書く。current_userヘルパーなどは自分で書かなければいけないので少し面倒。

モデルとコントローラが一貫している。

resource  :session
resources :users

いつもこれが正解ではないが、Rails wayに近い。

Sorceryの場合

migrationのgeneratorが用意されている。

class User < ActiveRecord::Base
  authenticates_with_sorcery!
end

セッション系は直接提供しないので、自分で書きましょう。

OmniAuthの場合

直接提供しないので、自分で書きましょう
デフォルトでは、認証開始が
GET /auth/:providerなのがいけてないので
POST /sessionに変えればよい。

OmniAuth.config.allowed_request_methods = [:post]

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, 'TWITTER_KEY', 'TWITTER_SECRET',
           request_path: '/session', callback_path: '/session/callback'
end

以下、認証系以外について続く…

Kaminari

ransack (meta_search)

補助リソースの名前を変えるGem