【Rails API】devise_token_auth実装〜Rspecテストまで【環境構築〜devise実装編】

## はじめに

### あばうと
メモ書き記事なので環境構築から順に書きます。
一応わかりやすいようにコマンドやコードなどは省略とかなしに書くつもりです。
なのでほぼほぼコピペでいけちゃいそうな記事になるかもしれませんが、学習中の方はひとつひとつ噛み砕いて理解してください。
gemやコードの説明などは対象外とします。
### やること
- 環境構築
- ログイン認証をdevise + devise_token_authで実装
- CSRF対策し外部ツールからPOST送信確認
- Rspecでのテスト

**記事の完成データはこちら**
https://github.com/daisuke131/devise_token_auth_rspec

## アプリ作成〜起動確認

アプリ作成

```sh
$ rails new devise_token_auth_sample --skip-bundle -d mysql
```

ここでは、vendor/bundleにbundle installしたい為、初期bundle installをスキップしてSQLはMySQLを使用するように作成しています。

次にbundle installします。

```sh
$ bundle install --path vendor/bundle
```

mysql2のエラー出る場合は、

```sh
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"
```
これでもダメなら教えてください。

DBcreateして起動確認します。

```sh
$ bundle exec rails db:create
$ bundle exec rails s
```

おっしゃです！

## Rspec導入

導入だけ先にやっときます。
generateコマンドを流した時自動でRspecファイルを生成してくれるので、先に導入する癖をつけています。

### gem追加

`factory_bot_rails`と`faker `はテストデータを作成するために必要なgemです。

```rb
group :development, :test do
# (中略) 
  gem "rspec-rails"
  gem "factory_bot_rails"
  gem "faker"
end
```
`bundle install`したあと、Rspecの設定ファイルをインストール

```sh
$ bundle exec rails g rspec:install
```

### .rspecファイルの修正

```rb
--require rails_helper
--format documentation
```
### rails_helper.rb修正
`require 'rspec/rails'`の下辺りに記述

```rails_helper.rb
Faker::Config.locale = :ja
```

`RSpec.configure do |config|`メソッド内に追記

```rails_helper.rb
config.include FactoryBot::Syntax::Methods
```

## devise実装

gem追加

```rb

gem "devise"
gem "devise_token_auth"
gem "rack-cors"
```

deviceの設定ファイルインストール

```sh
$ bundle exec rails g devise:install
```

device_token_authの設定ファイルインストール

```sh
$ bundle exec rails g devise_token_auth:install User auth
```

先にdeviseの設定ファイルを入れてからdevice_token_authの設定ファイルを入れないとめんどうなことになるので注意！

作成されたmigrationファイルに追記
コメントアウトで「## Trackable」と書いている部分

```~~~~~~~_devise_token_auth_create_users.rb
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.2]
  def change
    
    create_table(:users) do |t|
      ## Required
      t.string :provider, :null => false, :default => "email"
      t.string :uid, :null => false, :default => ""

      ## Database authenticatable
      t.string :encrypted_password, :null => false, :default => ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at
      t.boolean  :allow_password_change, :default => false

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable ここの部分追加
      t.integer  :sign_in_count, :default => 0, :null => false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.string   :current_sign_in_ip
      t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at

      ## User Info
      t.string :name
      t.string :nickname
      t.string :image
      t.string :email

      ## Tokens
      t.text :tokens

      t.timestamps
    end

    add_index :users, :email,                unique: true
    add_index :users, [:uid, :provider],     unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,       unique: true
  end
end
```

マイグレ！

```sh
$ bundle exec rails db:migrate
```

次はコントローラーを作っていくのですが、無駄なファイルを追加しないように`application.rb`に次の記述を追加します。

```config/application.rb
config.generators do |g|
  g.template_engine false
  g.javascripts false
  g.stylesheets false
  g.helper false
  g.test_framework :rspec,
  fixtures: true,
  fixture_replacement: :factory_bot,
  view_specs: false,
  routing_specs: false,
  helper_specs: false,
  controller_specs: false,
  request_specs: true
end
config.api_only = true
config.middleware.use ActionDispatch::Flash
```

追加場所がわからなかったらgitに上げているので参考にしてください。

コントローラの作成

```sh
$ bundle exec rails g controller api/v1/auth/registrations
```

`app > controllers > api > v1 > auth > registrations_controller.rb`にファイルが作成されたので↓のように書き換え。

```registrations_controller.rb
class Api::V1::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  private
    def sign_up_params
      params.permit(:name, :email, :password, :password_confirmation)
    end

    def account_update_params
      params.permit(:name, :email)
    end
end
```
route.rbの修正
`mount_devise_token_auth_for 'User', at: 'auth'`をネストしてあげる。

```route.rb
namespace :api do
  namespace :v1 do
    mount_devise_token_auth_for 'User', at: 'auth', controllers: {
      registrations: 'api/v1/auth/registrations'
    }
  end
end
```
## devise実装完了

次は、外部ツールからユーザーのデータを保存できるかなどを確認します。
[外部ツールで確認編](https://qiita.com/disk131/items/528bfde1456289ed9963)

すぐテストいくならこちら
[Rspecテスト編](https://qiita.com/disk131/items/a801e4bc11c8d64fed9a)