Railsでdeviseひとつで複数モデルを管理しよう


ウェブサービスなどでよく新規登録画面が`http://hoge.com/users/sign_up`と`/companies/sign_up`など、ユーザーの属性ごとに管理されているのを目にします。こいつはきっとモデルもきれいに分かれているんだろうなと思いを馳せつつ考えると、例えばセキュリティ的にuserとadminの管理はテーブルごとまるまる別個にしたいという場合だったり、もしコイツができたらいろいろと応用が効きそうなわけです。

すごーく気になったので調べてつくってみました。

```bash:導入環境
Ruby:   2.1.3
Rails:  4.2.1
devise: 3.5.1
```

**※deviseの基本的な導入方法などはすっ飛ばします。**

### 1. configに手を加える

```bash
$ rails g devise:install
```

無事deviseがインストールできたら`config/initializers/`配下に`devise.rb`が誕生すると思います。その中にこんな記述があるはず。

```ruby:/config/initializers/devise.rb
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
```

この最終行を、こう。

```ruby:/config/initializers/devise.rb
config.scoped_views = true
```

コメントアウトはもちろん外します。

### 2. deviseと関連したmodelを生成する
例えばUserモデルとAdminモデルなど、deviseと関連づけたいモデルを全て生成します。モデル名はまだ存在しないものを選んでください。

```bash
$ rails g devise user
$ rails g devise admin
```

### 3. 各modelに対応するcontrollerを生成する
先ほど生成した各modelに対して個別のコントローラーを作成してやります。コントローラーなので名前は複数形にしてあげてください。

``` bash
$ rails g devise:controllers users
$ rails g devise:controllers admins
```

### 4. 各modelに対応するviewを生成する
今度はモデル個別のviewを生成してやりましょう。コントローラー名と一致しないとうまく連携が取れないので注意してください。

```bash
$ rails g devise:views users
$ rails g devise:views admins
```

### 5. routingを設定する
いよいよルーティングをいじります。
今ルーティングはこうなっているはずです。

```ruby:/config/routes.rb
devise_for :users
devise_for :admins
```



```bash
                   Prefix Verb   URI Pattern                       Controller#Action
                   				#[--- 中略 ---]#
cancel_admin_registration GET    /admins/cancel(.:format)          devise/registrations#cancel
       admin_registration POST   /admins(.:format)                 devise/registrations#create
   new_admin_registration GET    /admins/sign_up(.:format)         devise/registrations#new
  edit_admin_registration GET    /admins/edit(.:format)            devise/registrations#edit
                          PATCH  /admins(.:format)                 devise/registrations#update
                          PUT    /admins(.:format)                 devise/registrations#update
                          DELETE /admins(.:format)                 devise/registrations#destroy
                          		#[--- 中略 ---]#
 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
                          PATCH  /users(.:format)                  devise/registrations#update
                          PUT    /users(.:format)                  devise/registrations#update
                          DELETE /users(.:format)                  devise/registrations#destroy
                          		#[--- 中略 ---]#
```

恐るべき共通具合。これだと宜しくありませんので、ちょいっと変えてやります。

```ruby:/config/routes.rb
devise_for :admins, controllers: {
  sessions:      'admins/sessions',
  passwords:     'admins/passwords',
  registrations: 'admins/registrations'
}
devise_for :users, controllers: {
  sessions:      'users/sessions',
  passwords:     'users/passwords',
  registrations: 'users/registrations'
}
```
```bash
                   Prefix Verb   URI Pattern                       Controller#Action
                   				#[--- 中略 ---]#
cancel_admin_registration GET    /admins/cancel(.:format)          admins/registrations#cancel
       admin_registration POST   /admins(.:format)                 admins/registrations#create
   new_admin_registration GET    /admins/sign_up(.:format)         admins/registrations#new
  edit_admin_registration GET    /admins/edit(.:format)            admins/registrations#edit
                          PATCH  /admins(.:format)                 admins/registrations#update
                          PUT    /admins(.:format)                 admins/registrations#update
                          DELETE /admins(.:format)                 admins/registrations#destroy
                          		#[--- 中略 ---]#
 cancel_user_registration GET    /users/cancel(.:format)           users/registrations#cancel
        user_registration POST   /users(.:format)                  users/registrations#create
    new_user_registration GET    /users/sign_up(.:format)          users/registrations#new
   edit_user_registration GET    /users/edit(.:format)             users/registrations#edit
                          PATCH  /users(.:format)                  users/registrations#update
                          PUT    /users(.:format)                  users/registrations#update
                          DELETE /users(.:format)                  users/registrations#destroy
                          		#[--- 中略 ---]#
```
これモデルもコントローラーもビューも別個のユーザー管理ができるようになりました。

### 6. 後処理をする
もう使わないビューファイルが生成されてしまっているので消します。

```bash
$ rails d devise:views

#      invoke  #Devise::Generators::SharedViewsGenerator
#      remove    app/views/devise/shared/_links.html.erb
#      invoke  form_for
#      remove    app/views/devise/confirmations/new.html.erb
#      remove    app/views/devise/passwords/edit.html.erb
#      remove    app/views/devise/passwords/new.html.erb
#      remove    app/views/devise/registrations/edit.html.erb
#      remove    app/views/devise/registrations/new.html.erb
#      remove    app/views/devise/sessions/new.html.erb
#      remove    app/views/devise/unlocks/new.html.erb
#      invoke  erb
#      remove    app/views/devise/mailer/confirmation_instructions.html.erb
#      remove    app/views/devise/mailer/reset_password_instructions.html.erb
#      remove    app/views/devise/mailer/unlock_instructions.html.erb
```
あとはご自由にモデル・コントローラー・ビューをいじりまくって素敵deviseライフを満喫してください。パス名ももちろん別個のものなので管理もラクラクです。