LoginSignup
37
37

More than 5 years have passed since last update.

Rails + Vue.jsでwebアプリケーション開発

Last updated at Posted at 2018-06-24

Railsのwebpackを使用して、SPAの開発ができるということで、実際に開発しているが、あまり、Rails + Vue.jsの開発メモがなかったので、はまったところなどメモしたいと思う。
開発環境の構築、Vue.jsの使い方などは、今回は割愛させていただきます。

2019/01/27 後述

RailsとVue.jsを共存させるというのは難しいなと一通り開発してみて感じた。本来、コードをスマートにするために使われるフレームワークの良さが失われてしまう。2018年の1年間フロントまわりの技術をさらってみて、本記事のようにサーバーサイドとフロントを共存させてしまうよりも、サーバーサイドはAPIとしての役割のみ持たせて(RailsにはAPIモードがある)、あとはフロントに任せるという、双方のコードを分離させた方が開発がスムーズになると今は考えている。そのため本記事の方法はあまり推奨しない。

環境情報

Ruby 2.4.0
Rails 5.1.0
rails/webpacke 3.1.0
Vue.js 2.5.13
vue-router3.0.1

Vueファイルを使用する

vue.jsを導入した時にできるファイルhello_vue.jsがvue.jsを動かす基盤となる。

トップページを作ってみる

app/javascript/packs/hello_vue.js
import Vue from 'vue/dist/vue.esm'
import router from './routes.js';

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#app',
    router
  })
});

importで、yarnで導入したライブラリを読み込む。この場合だと、vue/dist/vue.esmを使用するよ〜、./routes.js(こいつは、後で触れるが、ルーティングの設定をしているファイル)を使用する宣言をしている。それぞれ、Vueやrouterという名前をつけて、Vueのインスタンス化をするときに、読んであげる。それが、new Vue({})の中である。el: '#app'というのは、Vueのルールで、このappで囲まれたところでしか、Vueは使えない。

vue-routerを使用する

vue.jsのルーティングはvue-routerを使用してあげる。先ほどの、hello_vue.jsに記述した。

app/javascript/packs/routes.js
import Vue from 'vue/dist/vue.esm';
import VueRouter from 'vue-router';
import Index from './components/app.vue';

Vue.use(VueRouter);

const router = new VueRouter({
  mode: 'history',
    routes: [
    { path: '/', component: Index, name: 'root_path' },
  ]
});

export default router;

先ほどのhello_vue.jsと同様。どのファイルを使用するかを記述する。
{ path: 'アクセスされるURL', '使用するコンポーネント', 'pathの名前'}
こんな感じのルールで書く。これで、トップページにアクセスすると、app.vueで記述した画面に遷移するように設定ができた。

ここまで、作ったものをレイアウトに乗せてあげればOK。
あとは、このrouterを使用するために、Railsのapplication.html.erbにrouter-viewタグを追加する。

application.html.erb
<head>
 <%= javascript_pack_tag 'hello_vue' %>
</head>
<body>
  <div id="app">
    <router-view></router-view>
  </div>
</body>

こうすることによって、先ほど、hello_vue.jsで書いたid = appの下はvue.jsが動くので、appのdivでrouter-viewを挟んであげれば、指定されたpathに対して、componentsを描画するというようにvue.jsが動くようになる。

実際に開発する

てな、感じでトップページは作ることは簡単にできるのだが、実際に開発してみるとハマるポイントが多い。
実際に作業の流れを例に示す。

①vue.jsでフォームを作る

まずは、先ほどと同じ要領で、ルーティングの設定をする。

app/javascript/packs/routes.js
import Vue from 'vue/dist/vue.esm';
import VueRouter from 'vue-router';
import Index from './components/app.vue';
import Question from './components/question.vue';

Vue.use(VueRouter);

const router = new VueRouter({
  mode: 'history',
    routes: [
    { path: '/', component: Index, name: 'root_path' },
    { path: '/question/new', component: Question, name: 'question_new_path' },
  ]
});

export default router;

question/newというパスにきたら、Questionコンポーネントを使用するようにルーティング設定。Questionコンポーネントは、question.vueというファイルをcomponentsの下に新規追加する。

app/javascript/packs/components/question.vue
<template>
    <div>
        <div class="container">
            <form>
                <div class="form-group">
                    <label for="form_title">質問名</label>
                    <input type="text" name="question[content]" class="form-control" id="content">
                    <button type="button" class="btn btn-primary" v-on:click="postQuestion">作成する</button>
                </div>
                    </form>
        </div>
    </div>
</template>
<script>
    export default {
        data: function () {
            return {
                question: {
                    content: null,
                },
            }
        },
        methods: {
        }
    }
</script>

ただ、これだけだと、/question/newにアクセスしてもRailsのルーティングエラーになってしまう。
そのため、Railsの開発同様、Question_cotroller.rbとviews/questions/new.html.erb、そして、rails側のルーティングも記述しないといけない。

②保存処理を実装する

ここまでで、DBなどを活用しない画面は作ることができるが、やはりシステムを作るなら、DBに値を保存する機能が必須である。
ここからは、Vue側から、Railsに値を渡してデータを保存する機能を作って行く。

データを保存する際には、ajax処理を使うのだが、せっかくVue.jsを使っているので、axiosを使用する。
yarn add axiosでaxiosをインストールしたら、

app/javascript/packs/components/question.vue
<script>
    import axios from 'axios'

    export default {
        data: function () {
            return {
                question: {
                    content: null,
                },
        question_id: null
            }
        },
        methods: {
         postQuestion: function(){
           axios.post('/api/quetion', {
             content: this.question.content,
          }).then((res)
             this.question_id = res.data._id
          });
         }
       }
    }
</script>

postの第一引数に、保存処理をするコントローラーのパス、第二引数に値を渡せば簡単にajax処理ができる。

/api/question_controller.rb
    def create
        begin
            @question = Question.create!(question_params)
            respond_to do |format|
                format.html { redirect_to @question, notice: 'Question was successfully created.' }
                format.json { render :new, status: :created, location: @question }
            end
        rescue => e
            logger.error(e.message)
            format.html { render :new }
            format.json { render json: @question.errors, status: :unprocessable_entity }
        end

    end

    def question_params
        params.require(:question).permit(
            :content
        )
    end

基本的に、サーバーサイドに値が渡ってきたら、Railsのやり方でやればOK

③サーバーサイドからの値を取得する

Railsの場合、コントローラーから変数をerbファイルに渡すことができたが、vue.jsの場合はそれができない。
そのため、基本的に値はコントローラーでjsonデータをjson.jbuilderを使ってview側に渡す形になる。

/views/api/question.json.jbuilder
json.question_id @question.id

基本的に、これらの要領でいけば、VueとRailsを使ってデータのやり取りができるはず。

参照

Vue.jsとRailsでTODOアプリのチュートリアルみたいなものを作ってみた
Vuejs – RE:ENGINES
Rails 5.1 + Vue.js で開発を行う - part2 Ajax で GET しよう!

37
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
37