deviseのみを用いて２つの異なるログイン機能を実装する方法（ruby on rails）

# はじめに

久しぶりの投稿になります。（最近コーディング以外のことをやっていたせいでqiitaに記事が書けなかった^^;）

ECサイトの開発でrails-admin等の管理者機能作成gemを使わずに、deviseのみを用いて管理者とユーザーのログイン機能を実装した時に思いのほか詰まったので備忘録がてらメモを残しときます。

開発環境
仮想環境：Linux（vagrant）
rails 5.2.3
ruby 2.5.7

##サンプルプロジェクトの作成
まずはrails newでサンプルとなるプロジェクトの作成を行いましょう。

```ruby:コンソール
$ rails new devise-sample
```
これでサンプルプロジェクトの作成完了です。

##deviseのインストール
まずはgemファイルにdeviseを入れてましょう。（私は毎回ファイルの一番下にdeviseを追加しています）

```ruby:Gemfile
.
.
.
gem 'devise'
```

```ruby:コンソール
$ bundle install
```

```ruby:コンソール
$ rails g devise:install
```

これでdeviseを使う準備は完了です。

##モデルの作成
ユーザーと管理者のログイン機能を別々に作るために２つのモデルとコントローラーを作成していきたいと思います。

```ruby:コンソール
$ rails g devise User
```
```ruby:コンソール
$ rails g devise Admin
```
マイグレーションファイルが作成されたのでデーターベースに反映させしましょう。

```ruby:コンソール
$ rails db:migrate
```

これでモデルの作成は完了しました。

この時点でサーバーを起動して以下のURLに飛ぶとログインと新規登録画面のページに遷移できます。
ドメイン名/users/sign_in
ドメイン名/users/sign_up
ドメイン名/admins/sign_in
ドメイン名/admins/sign_up

<img width="466" alt="スクリーンショット 2019-11-15 18.29.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508303/703813c8-9e05-eaa0-729e-e35711ece8ae.png">
<img width="627" alt="スクリーンショット 2019-11-15 18.29.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508303/b19fbb35-aa83-2ba3-e29e-8399760b9c06.png">

管理者、ユーザーどちらも同じ画面になっているはずです。

##コントローラーとビューの作成
ここでもユーザーと管理者側の機能を分けて作成しましょう。

```ruby:コンソール
$ rails g devise:controllers users
```
```ruby:コンソール
$ rails g devise:controllers admins
```

```ruby:コンソール
$ rails g devise:views users
```
```ruby:コンソール
$ rails g devise:views admins
```

これでadminのログイン画面をいじってみようかな。

```ruby:app/view/admins/sessions/new.html.erb
<h1>海鮮丼美味しかった</h1>  #ここに新規の書き込み
<h2>Log in</h2>
.
.
省略
<% end %>
<%= render "admins/shared/links" %>
```

<img width="477" alt="スクリーンショット 2019-11-15 19.59.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508303/16a915e3-fac0-be73-f480-3bf18f57a6fe.png">


あれ？viewの変更が反映されてない！！

##deviseモデルとコントローラーの紐づけ
調べていくとなぜかモデルとコントローラーが紐づいておらず、deviseがモデルを作成した時に隠し持っているviewを表示しているとのこと。困った。

そういえばコントローラーを作った時にコンソールになんか出てたな

```ruby:コンソール
$ rails g devise:controllers Admin

Running via Spring preloader in process 23705
      create  app/controllers/Admin/confirmations_controller.rb
      create  app/controllers/Admin/passwords_controller.rb
      create  app/controllers/Admin/registrations_controller.rb
      create  app/controllers/Admin/sessions_controller.rb
      create  app/controllers/Admin/unlocks_controller.rb
      create  app/controllers/Admin/omniauth_callbacks_controller.rb
===============================================================================

Some setup you must do manually if you haven't yet:

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

===============================================================================
```
セットアップはまだ終了しておらずにroutesをFor example:みたいに変えろとのこと。
やってみる。

```ruby:config/routes.rb
Rails.application.routes.draw do
  devise_for :admins, controller: {
        sessions: 'admins/sessions'
    }
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```
サーバー立ち上げて見てみる。
<img width="353" alt="スクリーンショット 2019-11-15 20.20.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508303/b58a198e-836d-1415-ece2-df141106cc30.png">

だめだ、「海鮮丼美味しかった」が表示されない！！

色々解決策をググってみる。
参考になりそうな記事を発見！！
http://katahirado.hatenablog.com/entry/2014/08/16/180718
https://qiita.com/kawasakiatsushi/items/8209a979d86ab3468799

試行錯誤して実装してみた。

```ruby:config/routes.rb
Rails.application.routes.draw do
  namespace :admins do
    devise_for :admins, :controller => {
    }
  end
  devise_for :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
```

再びサーバー立ち上げ。

<img width="432" alt="スクリーンショット 2019-11-16 0.48.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508303/cdf44429-490b-d911-da6c-2f17eab9dd58.png">

無事にモデルとコントローラーが紐づいてviewに書き込んだ『海鮮丼美味しかった』が表示できました。

namespaceの影響で
元：ドメイン名/admins/sign_up
今：ドメイン名/admins/admins/sign_up
に変化してしまってます。

他にも管理者とユーザーでログイン、ログアウトのリダイレクト先の設定など、もう一苦労あったのですがそれはまた別の機会に。

##最後に
余談ではありますがgemを用いてコードをブラックボックスとして実装すると応用が効きにくくなるので、gemのソースコードをgitから落として見た方がいいなと感じました。

それではまた！！