Rails + Vue.js + mysql のprojectをherokuにdeployした

# はじめに
この記事は、参考にした記事を上げつつ、私が行った手順を追記したような作業ログ的なものになります。
railsの記事を探すと、`rails generate scafford` や `rails g controller sample`といったような、railsのgenerateをしているものが多いですが、
今回は何もgenerateしませんでした。


# 開発環境
Mac OS Sierra

# rubyとrailsをinstall
rbenvを使用してinstallしました。

rbenv を利用した Ruby 環境の構築
https://dev.classmethod.jp/server-side/language/build-ruby-environment-by-rbenv/

rubyをinstall後にrailsをinstallします。

```
gem install rails
```

# Rails + Vue.js + mysql のプロジェクトを作成する
```
$ rails new sample --webpack=vue -d mysql
```

# 必要なものをinstallする
```
$ brew install yarn
$ yarn add vue-router
$ yarn add axios
```

```text:Gemfile
# for heroku
gem 'rails_12factor', group: :production 

# for Materialize
gem 'jquery-rails'
gem 'jquery-turbolinks'
gem 'materialize-sass'
gem 'material_icons'
```

Gemfileに追記後

```
$ bundle install
```

その後こちらを参考に、`app/assets/stylesheets/application.scss`と`app/assets/javascripts/application.js`に追記
https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11#materialize%E3%81%AE%E5%B0%8E%E5%85%A5

# mysqlの準備
developmentがlocalで`rails s`したときのもので、
productionがherokuで接続されるdatabaseになります。
productionはherokuにdeployする際、また作業を行うので、まずは`rails s`で起動できるようにします。

`config/database.yml`を見ます。
localで `rails s`したときに、development にかかれているdatabaseに接続されます。
mysqlでdatabaseを作成します。

```yml:config/database.yml
development:
    <<: *default
    database: sample_development
```

```
$ mysql -u root
mysql> show databases
mysql> create database sample_development
```

# vue jsを表示する
vueを作成して、 `rails s`でページを表示できるようにします。
参考: vue jsの表示確認
https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11#vuejs%E3%81%AE%E8%A1%A8%E7%A4%BA%E7%A2%BA%E8%AA%8D

```
$ rails s
```

# server側でapiを作る
`api/send`を作成して、送られてきたtextをそのまま返す以下のようなapiを作成します。

```json
# リクエスト
POST api/send, { text: 'test send' }

# レスポンス
{ status: 200, message: `text send`}
```

まずは、routerを以下のようにします。

```ruby:config/router.rb
Rails.application.routes.draw do
  root to: 'home#index'

  # apiはapiのnamespaceに作成する
  namespace :api, format: 'json' do
    post 'send' => 'send#send'
  end

  # getは全て、indexにredirect
  get '*path' => 'home#index'
end
```

後に、`vue-router`でroutingを行い、その後にブラウザの更新を行うと、
rails側でroutingできなくてエラーが出るので、get methodは全てredirectさせています。

次に `app/controllers/api/send_controller.rb` を作成します。
apiを作成する際は、namespaceを`api`にしたので、`app/controllers/api/`以下にfileを作成します。
`params`にリクエストparamaterが入ってきます。

```ruby:app/controllers/api/send_controller.rb
class Api::SendController < ApplicationController
  def send
    @text = params[:text]
    render status: 200, json: { status: 200, message: @text }
  end
end
```

# vueを更に拡張する。

参考: コンポーネントを使ってヘッダーを作成
https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%83%98%E3%83%83%E3%83%80%E3%83%BC%E3%82%92%E4%BD%9C%E6%88%90

参考: Vue-Routerを使用してSPAっぽく
https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11#vue-router%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6spa%E3%81%A3%E3%81%BD%E3%81%8F

参考: Axiosを使ってAPI通信
https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11#axios%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6api%E9%80%9A%E4%BF%A1

私は、rails側のviewをいじりたくなかったので、以下の様にしました。

```eruby:app/views/home/index.html.erb
<div id="app">
  <app></app>
</div>

<%= javascript_pack_tag 'sample' %>
```

```app/javascript/packs/sample.js
import Vue from 'vue/dist/vue.esm.js'
import Router from './router/router'
import App from '../app'

var app = new Vue({
  router: Router,
  el: '#app',
  components: {
    'app': App
  }
});
```

```app/javascript/app.vue
<template>
  <div id="app">
    <navbar></navbar>
    <div class="container">
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
import Navbar from 'packs/components/header'
export default {
  components: {
    Navbar,
  },
}
</script>

<style scoped>
</style>
```

# buttonを押したときにaxiosでPOSTリクエストを送る
buttonを作成して、`axois`でPOSTを送るものを作成しました。

私の環境では、`axios`を使用する際、rails側で`ActionController::InvalidAuthenticityToken`のエラーが出ました。
そのため、以下の様に、`X-CSRF-TOKEN`をheaderに追記しました。

参考: railsでaxiosを使用してpostする
https://qiita.com/sukechansan/items/738b4bdaffc07c337a70

```javascript
<template>
  ...
    <button @click="send"><button>
  ...
</template>

<script>
import axios from 'axios'

export default {
  data: function () {
    return {
      text: '',
    }
  },
  methods: {
    send () {
      axios.defaults.headers['X-CSRF-TOKEN'] = $('meta[name=csrf-token]').attr('content')
      axios.post('/api/send', { text: this.text}).then((res) => {})
    }
  },
}
```

# herokuにdeploy
参考: Heroku + MySQL + Rails + Mac とりあえず構築まで
https://qiita.com/htakahashi/items/8d210d7f65e8b64be6a6#heroku%E3%81%AB%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E7%99%BB%E9%8C%B2

今まで作成したものを、herokuにdeployします。
Procfileを作成


```text:Procfile
web: bundle exec rails server -p $PORT
```

heroku appsを作成

```
$ heroku login
$ heroku create
$ heroku addons:add cleardb:ignite
$ heroku config | grep CLEARDB_DATABASE_URL
CLEARDB_DATABASE_URL: mysql://[ユーザ名]:[パスワード]@[ホスト名]/[スキーマ名]?reconnect=true

$ heroku config:set DATABASE_URL='mysql2://[ユーザ名]:[パスワード]@[ホスト名]/[スキーマ名]'
$ heroku config:set DATABASE_PASSWORD ='[パスワード]'
$ heroku run rake db:create
$ heroku run rake db:migrate
```

`DATABASE_URL`は`CLEARDB_DATABASE_URL`とほぼ同じで良いですが、`mysql`の部分だけ`mysql2`に変更する必要があります。

productionのRDSの接続先を変更
https://qiita.com/htakahashi/items/8d210d7f65e8b64be6a6#rails%E3%81%AEdb%E6%8E%A5%E7%B6%9A%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E3%81%88%E3%81%BE%E3%81%99

あとは git を操作してpushするだけです。

```
$ git init
$ git add .
$ git commit -m "create project."
$ git push heroku master
$ heroku open
```

これでdeploy終了です。
お疲れ様でした。