Rails 5.1 + Vue.js + Vuex + vue-routerの初期設定

# Rails 5.1 + Vue.js + Vuex + vue-routerの初期設定
- Rails 5.1でVue.jsの単一コンポーネントファイルを使おうとしたら初期設定が色々と面倒だったので、設定し終えた状態でGitHubに置いておきました。良かったら使ってください。
- https://github.com/midwhite/VueOnRailsTemplate

## 使っているもの
- Ruby 2.4.1
- Rails 5.1.4
- Vue.js 2.5.9
- Vuex 3.0.1
- vue-router 3.0.1
- webpacker 3.0.2
- MySQL 5.6
- bootstrap 4.0.0-beta

## ポイント
### app/javascript/pack/application.js
```js
import Vue from 'vue';
import Vuex from 'vuex';
import VueRouter from 'vue-router';
import store from '../store';
import router from '../routes';
import App from '../app';

import '../assets/css/application';

Vue.use(Vuex);
Vue.use(VueRouter);

document.addEventListener('DOMContentLoaded', () => {
  new Vue({
    el: '#application',
    store: new Vuex.Store(store),
    router,
    render: (h) => h(App),
  });
});
```
- `Vue.use(Vuex)` で使ったVuexをそのままVueインスタンス生成時の `new Vuex.Store()` で使わないと `Uncaught Error: [vuex] must call Vue.use(Vuex) before creating a store instance.` というエラーが発生する。
- Vueインスタンス生成時に `render: (h) => h(App)` を使わないと `[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.` というエラーが発生する。

### app/javascript/routes.js
- フロント側のルーティング設定を記述

```javascript
import VueRouter from 'vue-router';
import WelcomePage from './components/shared/welcome';

const routes = [{
  path: '/', component: WelcomePage,
}];

export default new VueRouter({ routes });
```

### config/routes.rb
- 画面のルーティングはフロント側で管理したいため、サーバー側ではルートパス以外へのGETリクエストをルートパスにリダイレクトする
- APIリクエストの処理は `namespace :api` の中に記述する

```ruby
Rails.application.routes.draw do
  root to: 'homes#welcome'

  namespace :api do
  end

  get '*path', to: 'homes#redirect_to_root'
end
```

### app/javascript/app.vue
- 共通化したヘッダーとフッターを置き、ルーティングにマッチしたコンポーネントをその間に表示

```javascript
<template>
  <div id="app">
    <header-component />
    <router-view />
    <footer-component />
  </div>
</template>

<script>
import HeaderComponent from './components/shared/header';
import FooterComponent from './components/shared/footer';

export default {
  components: {
    HeaderComponent,
    FooterComponent,
  },
}
</script>

<style scoped>
</style>
```

### app/javascript/assets/css/application.css
- アプリケーション全体に適用したいスタイルを記述する

```css
a, a:hover, a:focus {
  color: #1E88E5;
  text-decoration: none;
}
```

### app/javascript/store/axios.js
- axiosで普通にPOST / PUT / DELETEリクエストをRailsに送るとトークン認証エラーが返るため、metaタグの中からauthenticity_tokenを探してリクエストパラメータにセットする

```javascript
import axios from 'axios';

const setToken = (params) => {
  const tags = document.getElementsByTagName("meta");
  for (let i=0; i<tags.length; i++) {
    if (tags[i].name === "csrf-token") {
      params.authenticity_token = tags[i].content;
      break;
    }
  }
  return params;
}

export default {
  get: (path, params = {}) => {
    return axios.get(path, { params });
  },
  post: (path, params = {}) => {
    return axios.post(path, setToken(params));
  },
  put: (path, params = {}) => {
    return axios.put(path, setToken(params));
  },
  delete: (path, params = {}) => {
    return axios.delete(path, { params: setToken(params) });
  },
}
```

## 起動方法
- 各種ライブラリをインストール
- foremanを使っているので `npm start` だけでRailsサーバーとフロント側のコンパイルを起動できる
- 起動後に `http://localhost:3000` へアクセスすればすぐ開発に着手できる

```console
$ bundle install
$ npm install
$ npm start
```