DeviseとDevise token authを共存させる（後から追加する）

## 追記（2019年11月7日）
条件はわかりませんが、おそらくバージョンによってInvalidAuthenticityTokenエラーがでる場合があります。

```
ActionController::InvalidAuthenticityToken in DeviseTokenAuth::RegistrationsController#create
```

その場合はprotect_from_forgeryをフォーマットによって変更することで対応しています。
これが正しい方法かなのかはわかりません。誰か教えてください。

```ruby:controllers/application_controller
class ApplicationController < ActionController::Base
  protect_from_forgery unless: -> { request.format.json? } 
  ...
end
```

## Devise Token Authについて
Deviseのユーザー登録機能を利用して、トークンの発行、トークンによる認証を可能にするgemです。
注意点として、

・普通に入れるとAPI専用として作ることになる（/users/sign_inとか使えない）
・（Deviseのみで開発していたアプリへの）後からDevise Token Authを追加することを前提に作られていない

ということで、この二点を解決する方法を調べました。

## セットアップ
Gemfileに追加します。あとから追加する場合もこの状態にします。

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

```bash
bundle install #または bundle install --path vendor/bundle
```

## Deviseのインストール（運用中の場合はスキップ）
すでにDeviseが入っている場合は不要です。

```bash
rails generate devise:install
rails db:migrate
```

Deviseの詳細なセットアップについては、以下の記事が参考になります。https://qiita.com/cigalecigales/items/f4274088f20832252374

## Devise token authのインストール
次に、Devise token authをインストールします。

```bash
rails generate devise_token_auth:install User auth
```

## Routeを修正
```ruby:config/routes.rb
Rails.application.routes.draw do
  # 先にDevise用のルート
  devise_for :users

  # /api/v1/authでアクセス可能
  namespace :api do
    scope :v1 do
      mount_devise_token_auth_for 'User', at: 'auth'
    end
  end
end
```

## application_controller.rbを修正
通常のapplicatino_controller.rbに加えて、API用のapplication_controller.rbを作成します。

まずは通常のapplication_controllerを修正

```ruby:app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  #include DeviseTokenAuth::Concerns::SetUserByToken # この行を削除
  protect_from_forgery with: :exception
  before_filter :set_host # この行を追加

  def set_host
    Rails.application.routes.default_url_options[:host] = request.host_with_port
  end
end

```

Devise Token Auth用のapplication_controller.rbをapi/v1以下に作成

```ruby:app/controllers/api/v1/application_controller.rb
module Api
  module V1
    class ApplicationController < ActionController::API # Note: here is not ::BASE
      include DeviseTokenAuth::Concerns::SetUserByToken
      protect_from_forgery with: :null_session
    end
  end
end
```

## マイグレーションファイルを修正
Devise Token Auth用に生成されたマイグレーションファイルと、通常のDevise導入時に生成されたマイグレーションファイルを比較しながら、被っているものを削除してマイグレーションファイルを調整します。

## モデルを修正
```ruby:user.rb
class User < ApplicationRecord
  include DeviseTokenAuth::Concerns::User #ここだけがDevise Token Auth用

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end
```

## Initializerを修正
トークンの有効期限などを設定します。

```ruby:config/initializers/devise_token_auth.rb
DeviseTokenAuth.setup do |config|
  config.enable_standard_devise_support = true
  config.default_confirm_success_url = "confirmed"# この行を追加

  config.change_headers_on_each_request = false
  config.token_lifespan = 1.month

  config.headers_names = {:'access-token' => 'access-token',
                          :'client' => 'client',
                          :'expiry' => 'expiry',
                          :'uid' => 'uid',
                          :'token-type' => 'token-type' }
end
```

作りながら書いたので、不完全な内容になっているかもしれません。何か問題があれば随時修正します。