Rails 5 API + Vue.js + devise_token_authでTwitterと連携するSPAを作る（①RAILS編）



#概要
見習いエンジニアのナツキです。RailsのAPIモードを使ってVue.jsのシンプルなSPAを作ります。チュートリアルというよりは、開発ログです。この章では、RAILS部分がメインです。まだ未完成なので随時更新していきます。

#環境
```
$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.1
BuildVersion:	17B1003
```

```
Rails 5.2.0
ruby 2.3.1
```


※Qiita一件目の記事です！よろしくお願いします。

## 目標物
名前：hogekai
概要：Twitter上で気軽に〇〇会の開催を共有・募集することができるウェブサービス。

![スクリーンショット 2018-07-03 12.38.43.png](https://qiita-image-store.s3.amazonaws.com/0/224974/b7c289cd-b9f3-3982-9733-938df1678542.png)


## フレームワーク・ライブラリ・Gem
Rails 5 API
devise_token_auth/omniauth/omniauth-twitter
Vue/Vuex/Vue-router/Axios
Foreman/Webpacker
Element

## 対象者
・RailsとVue.jsの基本を理解しているが、APIやSPAの開発にまだ慣れていない人。
・トークン認証について理解を深めたい人。
・Elementを使ってスピード感のある開発をしたい人
・hogekaiの裏側が気になる人。

## 目次
①Rails編
1. Vue.js用のRails API アプリを作成する(forman + webpacker)
2. Rails APIにトークン認証を実装する(devise_token_auth)
3. Rails APIにTwitter認証を実装する(device_token_auth + omniauth）
4. 本番環境にデプロイ（Heroku）

②Vue編
1. SPAの動線をつくる（Vue-router)
2. Vue.js側のトークン認証を実装する（Axios + Vuex）
3. 本番環境にデプロイ（Heroku）

③その他(Element-UI)
1. landing pageを作る
2. Event投稿機能の作成(CRUD機能/form/modal)
3. Twitterイベント共有
4. Twitterメッセージ機能の作成
5. 本番環境にデプロイ（Heroku）

[未定]RailsでTwitter共有用の画像を動的に作成する（carrierwave）
1. 画像をAWS S3に保存する。
2. 画像を動的に変更して保存する。
3. 本番環境にデプロイ（Heroku）

## 注意
このnoteはチュートリアルというよりは、開発ログに近いものです。僕が参考にした記事をいくつか貼っていくので、わからなくなったらそちらにアクセスしてください。※英語の記事もガンガン紹介していきます！



# 1. Vue.js用のRails API アプリを作成する

foremanとwebpackerを使ってAPIを実装していきます。

## ボイラープレート(任意)

すでにベーシックな初期設定が済んでいるプロジェクトを見つけました。教科書通りベーシックな部分が網羅されています。テンポよく開発したい方はこれをつかうのもありです。（今回は学習もかねて一から作ります）

[参考記事：Rails 5.1 + Vue.js + Vuex + vue-routerの初期設定](https://qiita.com/takano-h/items/f5417cb6ff04c1d8c806)

## データベースの準備


herokuへのデプロイをスムーズに行う為に最初からpostgreqlで実装していきます。

[参考記事：MacのRailsアプリでPostgreSQLを使う方法](https://qiita.com/yh2020/items/8be3087004d100fe752b)


## DB設定の流れ


```terminal
# PostgreSQLのインストール（MAC版）
$brew install postgresql


# バージョンの確認・インストールされたかの確認
$ postgres --version
postgres (PostgreSQL) 10.4


# データベースクラスタの作成
$initdb /usr/local/var/postgres -E utf8


# PostgreSQLの起動
# ctr + cで終了
$postgres -D /usr/local/var/postgres


# データベースの確認
$psql -l


# PostgreSQLがデフォルトで参照するデータクラスを設定
$export PGDATA=/usr/local/var/postgres


# ユーザーの作成
$createuser hogekai_admin


# ユーザーの確認
$psql -q -c'select * from pg_user' postgres


# データベースの作成
$createdb hogekai_dev -O hogekai_admin


# 新しく作ったデータベースの確認
$ psql -q -c'select * from pg_user' hogekai_dev

# ユーザー権限の確認
# ここで　\du　と打つとユーザーの権限を確認。
# ここで　\q　と打つと通常の画面に戻る。
$psql -U hogekai_admin hogekai_dev


# ユーザー権限の変更(natsukingは自分のroot_userの名前)
# ここで　ALTER ROLE hogekai_admin WITH Superuserと打つとhogekai_adminにsuperuserの権限を与える。
# ALTER USER hogekai_admin WITH PASSWORD 'hogekai_password' と打つとパスワードの設定・変更。
# \du　と打つとユーザーの権限を確認。
# \q　と打つと通常の画面に戻る。

$psql -U natsuking hogekai_dev
```

ここで設定した情報はあとでRails側で使います。

## Rails プロジェクトの作成



[参考記事: Rails 5.1 + Vue.js の使い方](https://qiita.com/yoshiokaCB/items/07863e9b86f9d1a8f5e1)

[参考記事: Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた](https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11)

記事の通りに進まない部分も多いです。


```terminal
$rails new hogekai --webpack=vue --database=postgresql
```

database.ymlにデータベースの情報を書き足す


```database.yml
...

development:
  <<: *default
  database: hogekai_dev
  username: hogekai_admin
  password: hogekai_password
```

PostgreSQLを起動(もし既に動いていない場合)

```terminal
$postgres -D /usr/local/var/postgres
```

foremanを追加（RailsとVue両方の開発サーバーを管理するgem）

```Gemfile
// Gemfile

group :development do
 ...
 gem 'foreman'
end
```

```terminal
$bundle install
```

Procfileの作成（foremanの設定書のようなもの。root directory以下に作る）

```Procfile
// Procfile

rails: bundle exec rails server
webpack: ./bin/webpack-dev-server
foremanを起動するコマンド
```

```terminal
$ foreman start
```

この状態で**http\://localhost:5000/**にアクセスすると、RailsのHello World画面が表示されるはずです。

![picture_pc_04b8e7667cd2fa6902cff4b1a911f6e7.png](https://qiita-image-store.s3.amazonaws.com/0/224974/2ee25aed-c1e4-f6ef-f0c9-5d17c5cdb167.png)


次に、ルートパスで表示されるViewとControllerを作成します。


```terminal
$rails g controller home about
```

```routes.rb
Rails.application.routes.draw do
  root 'home#about'
  
end
```


これでもう一度localhost:5000にアクセスすると下の様な画面が表示されるはずです。


![picture_pc_f722307965f4469cfa6a520be1cf59f8.png](https://qiita-image-store.s3.amazonaws.com/0/224974/4b96d225-2097-b610-c980-d877e08a61df.png)


今度はデフォルトで生成されるapp.vueファイルを表示させて見ましょう。

```application.html.erb 
<!DOCTYPE html>
<html>
  <head>
    <title>Hogekai</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'hello_vue' %>
  </head>

  <body>
    <div id='hello'>
      {{message}}
      <app></app>
    </div>
  </body>
</html>
```

hello_vue.jsには、いろいろとコードが書かれていますが、必要なコードだけコメントインして、あとは削除。（Turbolinkを使いたい人は、一番下のコードを代わりにコメントイン。）

```hello_vue.js
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#hello',
    data: {
      message: "Can you say hello?"
    },
    components: { App }
  })
})
```


この時点で、下の画面が表示されたら成功です。

![picture_pc_1eecb888f0c92b73d714cac27d1a0d4f.png](https://qiita-image-store.s3.amazonaws.com/0/224974/58a350a5-e378-09c7-3b20-acc838532b85.png)


# 2. Rails APIにトークン認証を実装する

hogekaiでは、twitter認証しか使いませんが、普通のパスワード認証の実装も説明していきます。

[参考記事: devise token auth を使って簡単に早くAPIを作る 1](http://clc.gonna.jp/2017/01/post-1306/)

必要な部分だけ参照。

## Gemのインストール

```Gemfile
// Gemfile
...
gem 'omniauth'
gem 'devise'
gem 'devise_token_auth'
gem 'rack-cors'
```

```terminal
$bundle install
```


## devise_token_authをインストール＆User modelの作成

```terminal
$rails g devise_token_auth:install User auth
```

## migrationファイルの編集
confirmableの部分を今回はコメントアウトします。

```migration_fileXXX.rb
## db/migrate/生成されたファイルの名前

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.json :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
```

```terminal
$rails db:migrate
```


## 認証用のAPI controllerを作成


```terminal
$ rails g controller api/v1/auth/registrations
```

```registrations_controller.rb
// controllers/api/v1/auth/registrations_controller.rb

module Api
  module V1
    module Auth
      class 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
    end
  end
end
```

## パスを調整

```routes.rb
Rails.application.routes.draw do
 namespace :api, defaults: { format: :json } do
   scope :v1 do
     mount_devise_token_auth_for 'User', at: 'auth', controllers: {
         registrations: 'api/v1/auth/registrations'
     }
   end
 end
 root 'home#about'
end
```

パスを確認　api/v1/auth/registrations#newとかが表示されれば成功


```terminal
$rails routes
```
 
## initializerの設定


```devise_token_auth.rb
## config/initializers/devise_token_auth.rb

 ## falseに設定
 config.change_headers_on_each_request = false

 ## コメントイン　1.monthでもよい
 config.token_lifespan = 2.weeks 


## コメントイン
 config.headers_names = {:'access-token' => 'access-token',
                         :'client' => 'client',
                         :'expiry' => 'expiry',
                         :'uid' => 'uid',
                         :'token-type' => 'token-type' }
```

## CSRF対策（これがないとAPIリクエストでエラーがでる）

```application_controller.rb
class ApplicationController < ActionController::Base
 include DeviseTokenAuth::Concerns::SetUserByToken
 protect_from_forgery
end
```



## Postman
実際にAPIのリクエストを出して、jsonが返って来ることを確認していきます。今回はpostmanを使います。

[参考記事： APIの開発がむちゃくちゃ捗る「Postman」の使い方](https://www.webprofessional.jp/master-api-workflow-postman/)

今回テストするJSONデータ

```
{
    "name": "山口なつき",
    "email": "hogekai@example.com",
    "password": "123456789"
}
```

上記のデータを下のスクショの様にセットしてSendをクリック。

気をつける点：
１　POSTに設定してある？
２　http://localhost:5000/api/v1/auth
３　JSON(application/json)を選択してる？

![picture_pc_c53961726b5c2632e9fa2f9a226dd5fd.png](https://qiita-image-store.s3.amazonaws.com/0/224974/030f8efa-8b4b-764b-971a-c2d80b833d0f.png)


次のように結果が返ってくればOK

![picture_pc_566146b20d4bbb11881231a796cf9fd9.png](https://qiita-image-store.s3.amazonaws.com/0/224974/ddda7992-fc5d-6367-6c70-862a17189a93.png)

## ログイン
これでUserが登録されました。次はログインです。


{
    "email": "hogekai@example.com",
    "password": "123456789",
    "password_confirmation": "123456789"
}
この内容を先ほどと同じ様にPOSTします。ただし今回はlocalhost:5000/api/v1/auth/sign_inにリクエストを送ります。

![picture_pc_267a0078e5f4e58116c9c4925821f80c.png](https://qiita-image-store.s3.amazonaws.com/0/224974/55611892-8096-d59a-e909-50433cd37fbf.png)

こんな感じのものが返ってきたら成功です。ここで重要なのが、返ってきたHeadersの情報です。クリックした中身を確認します。

![picture_pc_5bc8e4380bab4921b4b66ab284819577.png](https://qiita-image-store.s3.amazonaws.com/0/224974/1c819b3a-2c95-0618-63a3-7fe1b7b14640.png)


- access-token
- client
- uid

の三つの値をメモります。これこそが、ユーザーのログイン状態を保つための重要な情報です。

![picture_pc_da3489e8ddee32f65d00fb52d0da12f7.png](https://qiita-image-store.s3.amazonaws.com/0/224974/2b82a902-f3ae-c2d4-4937-fd7a0aaae3ad.png)

## パスワードの変更
パスワードの変更に挑戦します。先ほどログインして返ってきたヘッダーの情報を使います。

```
access-token: C3e3Ok6aJzSE5TFG0N3-bg
client: cNOPygTl4G9Px0-uFoz6Zw
uid: hogekai@example.com
```

今度は, localhost:5000/api/v1/auth/passwordにPUTします。

今回はPOSTではなくPUTです。

```
{
    "password": "987654321",
    "password_confirmation": "987654321"
}
```

![picture_pc_23c3649ae650a1d2112d4034611eae7c.png](https://qiita-image-store.s3.amazonaws.com/0/224974/356c44cb-4d81-1ddf-5780-df6eddafa1b8.png)

![picture_pc_6fad9b6c90431337d7c892b020cf37d2.png](https://qiita-image-store.s3.amazonaws.com/0/224974/0d2bc62e-ea88-8300-ce24-d79896d7f3b4.png)

これでうまくいくと、下の様なJSONが返ってきます。

![picture_pc_4eb3b86696a1d3ae034f91823f610792.png](https://qiita-image-store.s3.amazonaws.com/0/224974/ff3575ef-effc-a6e8-f67f-1303e2db4c58.png)


## ユーザー情報の変更
今度はユーザー情報を変更してみます。localhost:5000/api/v1/auth に PUT。headerには、前回と同じuid, client, access-tokenを入れています。名前をひらがなから漢字に変えます。

```
{
    "name": "山口 夏生"
}
```

![picture_pc_77aeab518a6cd4321ec26e514260717d.png](https://qiita-image-store.s3.amazonaws.com/0/224974/e4bd9e36-b015-c594-e2ae-dfff2cfd2ce4.png)


![picture_pc_4eb3b86696a1d3ae034f91823f610792.png](https://qiita-image-store.s3.amazonaws.com/0/224974/2f6e6548-03e6-113f-53a0-88ab4d6c61f5.png)


これで下のJSONが返ってきたら成功。

![picture_pc_97adba662be87a4ff2ba8946ff60d013-2.png](https://qiita-image-store.s3.amazonaws.com/0/224974/27c368d3-5d61-109c-87c4-51f358e3a591.png)

パスワードを忘れた際の変更処理は、割愛します。参考記事を読んでください。


# 3. Rails APIにTwitter認証を実装する


パスワード認証ができたので、twitter認証にうつります。device_token_auth + omniauthで実装していきます。twitterのトークン認証の記事は地味に少なくて、苦労しました。

[omniauth omniauth_callbacks_controllerソースコード](https://github.com/lynndylanhurley/devise_token_auth/blob/master/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb)
[omniauth-twitter　公式ドキュメント](https://github.com/arunagw/omniauth-twitter)
[参考記事: Rails5のAPIモードでdevise_token_authとomniauthを使ったログインを試す](https://qiita.com/AQeNku/items/94485432184257799106)

## Gemのインストール
dotenvは、APIのSECRET等の情報を安全に管理するために使います。好みです。

```
// Gemfile 

gem 'omniauth-twitter'
gem 'dotenv-rails', '~> 2.1', '>= 2.1.1'
$bundle install
```

```
// 古いバージョンのdotenvがインストールされる可能性があるので
$bundle update
```

## Twitterアプリとdotenv
[参考記事：【Rails】『dotenv』で環境変数を管理する方法](http://vdeep.net/rubyonrails-dotenv)

Twitter アプリの登録＋そこで入手するAPP KEYとAPP SECRETが必要になるので、記事を参考に登録を進めてください。

[参考記事：リニューアル後のTwitterアプリの作成、登録法 APIキーの取得法](http://wpbeginner.ki-blog.biz/%E3%83%96%E3%83%AD%E3%82%B0/%E3%83%AA%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%A2%E3%83%AB%E5%BE%8C%E3%81%AEtwitter%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E4%BD%9C%E6%88%90%E3%80%81%E7%99%BB%E9%8C%B2%E6%B3%95-api%E3%82%AD%E3%83%BC/)

僕のはこんな感じ。localhostでは通りませんでした。
本番環境用のアプリもあとで登録するので、hogekai_devに変えました。

![picture_pc_220c4f2095be694ef0a31f6fe510b1d6.png](https://qiita-image-store.s3.amazonaws.com/0/224974/3c166dcf-1121-969f-1b42-361b330a060f.png)


そこで入手した情報を.envファイルの中に書き込みます。

```
// .env

TWITTER_KEY = "自分のConsumer Key"
TWITTER_SECRET = "自分のConsumer Secret"
```

## initializerの設定
initializer以下にomniauth.rbというファイルを作成して初期設定を書き込みます。

```initializer/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV.fetch("TWITTER_KEY"), ENV.fetch("TWITTER_SECRET"), callback_url: "http://127.0.0.1/api/v1/auth/twitter/callback"
end
```

## モデルの編集
モデルにも設定を付け加えます。

```user.rb
devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :omniauthable, :omniauth_providers: [:twitter]
twitter認証用のルートを追加します。
```

## パスの調整
```routes.rb
Rails.application.routes.draw do

  namespace :api, defaults: { format: :json } do
    scope :v1 do
      mount_devise_token_auth_for 'User', at: 'auth', controllers: {
          registrations: 'api/v1/auth/registrations',
          omniauth_callbacks: 'api/v1/auth/omniauth_callbacks'
      }
    end
  end
  root 'home#about'

end
```

## omniauth_callbacks_controllerの上書き
callback用のcontrollerをcontrollers/api/v1/auth/以下に作成します。もともとあるコードを上書きしています。このコードが最善のコードなのかはかなり怪しいですが、色々と試行錯誤しているうちにこれにたどり着きました。あとで説明するコードもあるのでコメントを参考にしてください。

```omniauth_callbakcs_controller.rb
module Api
  module V1
    module Auth
      class OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController
       
        // ①セッションを有効化
        skip_before_action :skip_session

        def redirect_callbacks
          super
        end
        def omniauth_success
          super
          update_auth_header
        end
        def omniauth_failure
          super
        end

        protected
            // ②credentialを保存
          def get_resource_from_auth_hash
            super
            @resource.credentials = auth_hash["credentials"]
            clean_resource
          end

          def render_data_or_redirect(message, data, user_data = {})
            if Rails.env.production?
              if ['inAppBrowser', 'newWindow'].include?(omniauth_window_type)
                render_data(message, user_data.merge(data))
              elsif auth_origin_url
                redirect_to DeviseTokenAuth::Url.generate(auth_origin_url, data.merge(blank: true))
              else
                fallback_render data[:error] || 'An error occurred'
              end
            else
               // わかりやすい様に開発時はjsonとして結果を返す
              render json: @resource, status: :ok
            end
          end

          // twitterから取得する絵文字を取り払うメソッドたち　DBエラーが起きるときにコメントイン
          // mysqlだと起きやすい
          def clean_resource
            @resource.name = strip_emoji(@resource.name)
            @resource.nickname = strip_emoji(@resource.nickname)
          end
          def strip_emoji(str)
            str.encode('SJIS', 'UTF-8', invalid: :replace, undef: :replace, replace: '').encode('UTF-8')
          end
      end
    end
  end
end
```

## credentialsコラムの追加
Twitter APIを経由してタイムラインとかに投稿したいことを想定して、twitter認証で返って来るアクセストークンをcredentialsというコラムに保存します。

credentialsコラムを作ります。

```terminal
$rails g migration addColumnToUsers credentials:text
$rails db:migrate
```

## application.rbを編集。

```application.rb
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module Hogekai
  class Application < Rails::Application

    
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore

    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*',
                 :headers => :any,
                 :expose => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
                 :methods => [:get, :post, :options, :delete, :put]
      end
    end
  end
end
```

## application_controller.rbを編集

```application_controller.rb
class ApplicationController < ActionController::Base
  include DeviseTokenAuth::Concerns::SetUserByToken
  protect_from_forgery
  before_action :skip_session

  protected
    def skip_session
      request.session_options[:skip] = true
    end
end
```


これで準備は整ったはずです。謎なコードも多いかと思いますが、公式ドキュメントやグーグルの記事を読んで理解してください。

## ブラウザーで確認
ではブラウザーから確認して見ましょう。http://127.0.0.1:5000/api/v1/auth/twitter でアクセスします。

こんな感じの画面がでるはずです。

![picture_pc_1280ae96cb80f28f2eba526aad5396a6.png](https://qiita-image-store.s3.amazonaws.com/0/224974/420250a8-5153-b5fe-b1cf-0df519cb6e78.png)

これでauthorize appをクリックして下の様なJSONが返ってくれば成功です。

![picture_pc_e888e45225e3b54ca4d34efa90c28fe0.png](https://qiita-image-store.s3.amazonaws.com/0/224974/40431223-c208-0cee-8e35-a71e27c443e5.png)

## ヘッダーの確認
パスワード認証の時と同じでヘッダーにはログイン状態をキープするためのトークン情報（uid, client, access-token）が入ってます。Google Chromeの開発ツールを使うと確認できます。

[参考記事：Chromeデベロッパー・ツールを使ってヘッダー情報を確認する](http://dev.blog.fairway.ne.jp/chrome%E3%83%87%E3%83%99%E3%83%AD%E3%83%83%E3%83%91%E3%83%BC%E3%83%BB%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E6%83%85%E5%A0%B1%E3%82%92/)

![picture_pc_a5acbd639042d649cbc718d3714fb2cf.png](https://qiita-image-store.s3.amazonaws.com/0/224974/d31ee87f-f6c3-d4dc-a16f-e217c24ec176.png)


これでTwitter認証もできました。今回作ったAPIをherokuでデプロイして見ましょう。

# 4. 本番環境にデプロイ

API側での認証機能は実装できたので、一度herokuにデプロイして本番環境で稼働してみます。
herokuのアカウントを持っていることを前提で進めます。

[参考記事：挫折した人必見！HerokuでRailsアプリを公開する方法](https://www.sejuku.net/blog/8178)


## heroku toolbaltのインストール

heroku toobaltが最新版であることを確認してください。僕の場合バージョンが古かったのでアップデートしました（Macを使ってます）。

```
$brew install heroku/brew/heroku
```

## heroku サーバーの作成

```
$heroku create hogekai
```

## デプロイ

まず自分のgitリポジトリーを最新の状態にアップデートします。

```
$git add .
$git commit -m 'add token authentication features to Rails API'
$git push origin master
```

## 環境変数を設定
これを行わないとデプロイするときにエラーがでます。
環境変数関連のコマンドはこちら [[heroku] 環境変数の操作](https://qiita.com/colorrabbit/items/18db3c97734f32ebdfde) から拝借しました。

```
# 環境変数一覧
$ heroku config

# 環境変数名を指定して参照
$ heroku config:get ENV_VAR_NAME

# 追加 (一応addも使えます)
$ heroku config:set ENV_VAR_NAME="value"

# 削除 (一応removeも使えます)
$ heroku config:unset ENV_VAR_NAME
```

では実際に環境変数を設定します。

```
$heroku config:set TWITTER_KEY="自分のTWITTER_KEY"
$heroku config:set TWITTER_SECRET="自分のTWITTER_SECRET"
``` 

## デプロイ

```
$git push heroku master
```

## トラブルシューティング

```
remote:        Devise.secret_key was not set. Please add the following to your Devise　initializer:
remote:
remote:          config.secret_key = 'シークレットキー'
```


初期設定ファイルを編集します。
secret_keyは、devise_token_authではなく、devise側で処理するものなので、新しくDevise.setupを付け足しました。別のファイルを作ってもいいです。

```initializers/devise_token_auth.rb
DeviseTokenAuth.setup do |config|
...
end

# ここから下をつけたす
Devise.setup do |config|
  config.secret_key = ENV.fetch('DEVISE_SECRET')
end
```

dotenvで管理します。

```
// .env
DEVISE_SECRET = 'シークレット'
```

herokuに環境変数を渡します。

```
$heroku config:set DEVISE_SECRET="シークレット"
```

リポジトリを更新します。

```
$git add .
$git commit -m 'add devise secret'
$git push origin master
```


もう一度デプロイしてみます。

```
$git push heroku master
```

いくつかwarningがでましたがうまく行きました。

![スクリーンショット 2018-07-03 2.28.20.png](https://qiita-image-store.s3.amazonaws.com/0/224974/30506acb-598f-04b3-bf4e-8b535e73c559.png)


## DBのマイグレーション

```
$heroku run rake db:migrate
```

下の様なカラフルなスクリーンが出たら成功です。
![スクリーンショット 2018-07-03 2.30.53.png](https://qiita-image-store.s3.amazonaws.com/0/224974/d2149851-94a5-8a7f-175e-a6707f7101bf.png)

## 開く

```
$heroku open
```

うまくトップ画面が表示されました！

![スクリーンショット 2018-07-03 2.31.57.png](https://qiita-image-store.s3.amazonaws.com/0/224974/ba762dd1-3a0b-2bbf-a5a4-0430c5c22717.png)

これでAPIも立ち上がっています。

## パスワート認証のテスト
試しにポストマンでパスワード認証を行います。
新しいパスを使いましょう。

![スクリーンショット 2018-07-03 2.34.36.png](https://qiita-image-store.s3.amazonaws.com/0/224974/c9dff19e-7c44-fc8a-2ef0-6a0cd3ed8881.png)

成功です！

![スクリーンショット 2018-07-03 2.36.52.png](https://qiita-image-store.s3.amazonaws.com/0/224974/47bb5139-5551-dc6a-fd17-3896beab0848.png)


ついでにパスワードの変更も試します。

![スクリーンショット 2018-07-03 2.39.11.png](https://qiita-image-store.s3.amazonaws.com/0/224974/215bc3e5-725e-e40b-7d95-326e0eedd5a8.png)

先ほど受け取ったヘッダーの情報を送ります。
![スクリーンショット 2018-07-03 2.39.18.png](https://qiita-image-store.s3.amazonaws.com/0/224974/de02e685-4452-551c-9d15-bb014619d8cf.png)


これも成功しました。
![スクリーンショット 2018-07-03 2.39.32.png](https://qiita-image-store.s3.amazonaws.com/0/224974/76bd77f8-9961-fb1d-07ac-df036bb0f721.png)

## Twitter認証のテスト
Twitterの認証は、ちょっと面倒です。callback urlが違うので開発用のものと本番環境用のアプリを別で登録します。今回は省略しますが、是非自身で挑戦してください。

本番用のKEYとSECRETを取得できたら、heroku側の環境変数を更新して完了です。
ローカルのconfigファイルをいじる方法もあるので、暇な人は調べてください。

# まとめ
今回は認証機能をRails APIに実装しました。次回は、Vue.jsの方をがっつりいじって行きます。