VueでRailsのAPIを叩く

VueとRailsで何をするか

前回バックエンドにRruby on Rails、フロントエンドにVue.jsとVuetifyを使ったDocker環境を構築しました。今回はRuby on Railsコンテナの中にAPIを用意してVue側からそれを叩き、シェルスクリプトを実行してみたいと思います。

これが実現すればブラウザからシェルスクリプトを実行出来る事になります。UIを選択式にすることでかなりの時短になる上に、机にいなくてもスマホを使って何処からでもシェルスクリプトを実行可能になります。

vue-routerを追加

Vue側の実装から取り掛かっていきます。まずはタブメニューから表示するコンテンツを切り替えるためのルーティングを実装したいので、vue-routerを導入します。いかのコマンドを実行してパッケージをインストールします。

$ npm install vue-router

front/src/main.jsに下記を記述します。

import Vue from 'vue'
import App from './App.vue'
import vuetify from '@/plugins/vuetify';
import router from './router'

Vue.config.productionTip = false

new Vue({
  vuetify,
  router,
  render: h => h(App)
}).$mount('#app')

front/src/router.jsに下記を記述します。

import Vue from 'vue'
import Router from 'vue-router'
import Shell from './components/Shell.vue'
import Rabbit from './components/Rabbit.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/shell',
      name: 'shell',
      component: Shell
    },
    {
      path: '/rabbit',
      name: 'rabbit',
      component: Rabbit
    }
  ]
})

これでルーティングの設定は完了です。

App.vueを作成

次は今回のVueプロジェクトのトップページとなるApp.vueを試作します。とても適当です。

<template>
  <div
    class="main"
  >
    <v-tabs
      fixed-tabs
      background-color="indigo"
    >
      <v-tab to="/shell">
        Shell
      </v-tab>
      <v-tab to="/rabbit">
        Rabbit
      </v-tab>
      <v-tab>
        Other
      </v-tab>
      <v-tab>
        Settings
      </v-tab>
      <v-tab>
        About
      </v-tab>
    </v-tabs>
    <v-main>
      <router-view></router-view>
    </v-main>
  </div>
</template>

<script>
export default {
  name: 'App',

  data: () => ({
    //
  }),
};
</script>

<style>
  .main {
    padding: 20px;
  }
</style>

Vueコンポーネント作成

Shell.vueコンポーネントを試作

次にfront/src/components/Shell.vuefront/src/components/Rabbit.vueの各コンポーネントを作成します。Shell.vueはバックエンドのRails APIを叩くためのフォームを作成しています。

<template>
  <v-form>
    <v-row
      class="arg-row"
    >
      <v-col
        cols="6"
        md="2"
      >
        <v-text-field
          v-model="argument1"
          label="引数1"
        />
      </v-col>
      <v-col
        cols="6"
        md="2"
      >
        <v-text-field
          v-model="argument2"
          label="引数2"
        />
      </v-col>
    </v-row>
    <v-btn
      color="primary"
      dark
      @click="excecuteShellScript"
    >
      EXECUTE
    </v-btn>
  </v-form>
</template>

<script>
  export default {
    data: function () {
      return {
        argument1: null,
        argument2: null
      }
    },
    methods: {
      excecuteShellScript: function () {
        console.log(this.argument1, this.argument2)
      }
    }
  }
</script>

<style>
  .arg-row {
    margin: 0 auto;
  }
</style>

Rabbit.vueの方は中身は適当で大丈夫です。ここでは使用しないのですがVuetifyのデバッグがしたかったのと今後作りたいものがあったのでファイルだけ用意しただけです。

「EXECUTE」ボタンを押してコンソールにフォームで入力した値が出力されていればShell.vueコンポーネントの作成は一旦成功です。まだ終わりじゃありませんが。

Rails APIの作成

ルーティング

Shell.vueからの非同期リクエストをコントローラにルーティングするためapi/config/routes.rbに下記を記述します。

Rails.application.routes.draw do
  namespace :api, format: 'json' do
    scope module: :script do
      resource :shell_script, only: %i[update], param: :message
    end
  end
end

コントローラ作成

次に先程のルーティング先となるコントローラを作成します。api/app/controllers/api/script/shell_scripts_controller.rbに下記を記述して下さい。

module Api
  module Script
    class ShellScriptsController < ActionController::API
      def update
        p params['arguments']['argument1']
      end
    end
  end
end

Shell.vueを改修

Vue.jsにaxiosを導入して非同期処理

続いてShell.vueから先程作成したRails APIを叩くために非同期でHTTPリクエストを送る処理を実装します。そのためにaxiosというライブラリをVueプロジェクトにインストールします。

$ npm install --save axios

Shell.vueも改修します。
※URLのホスト名に関しては各々の環境に合わせてください。

<script>
  import axios from 'axios'

  export default {
    data: function () {
      return {
        argument1: null,
        argument2: null
      }
    },
    methods: {
      excecuteShellScript: function () {
        const query = {
          arguments: {
            argument1: this.argument1,
            argument2: this.argument2
          }
        }
        axios.patch('http://【ローカルホストのIPアドレス】:3001/api/shell_script', query)
          .then((response) => {
            console.log(response);
          })
          .catch((error) => {
            console.log(error)
          })
      }
    }
  }
</script>

APIの動作確認

ここで「EXECUTE」ボタンを押してみてHTTPリクエストを飛ばせているか、またAPIが動作しているかを確認してみて下さい。下記のコマンドでRailsコンテナのログを出力してみてargumentsの値を受け取れていれば成功です。

$ docker logs 【Ruby on Railsのコンテナ名】 -f

APIが実行する用のシェルスクリプト作成

現状ログに出力するだけの処理でしたが次はシェルスクリプトを実行させてみましょう。そのためにshell_scripts_controller.rbコントローラに実行させるシェルスクリプトを作成します。api/lib/scripts/date.shに下記を記述して下さい。

#!/bin/bash
cd /app/lib/scripts
echo `date` > ./hoge

shell_scripts_controller.rbを下記の様に書き直して下さい。

module Api
  module Script
    class ImageScraypingsController < ActionController::API
      def update
        p params['arguments']['argument1']
        system('bash ./lib/scripts/date.sh')
      end
    end
  end
end

これで全ての準備が完了しました。「EXECUTE」ボタンを押してみて下さい。Shell.vueから非同期でRails APIにリクエストが送られ、ShellScriptsControolerがそれを受けてdate.shを実行します。するとhogeファイルが作成されて時刻が書き換えられている筈です。VueからAPIを叩くという目標が達成出来ました。

終わりに

今回はVueでRailsのAPIを叩いてみましたが、この非同期でAPIを叩くという行為は非常に重要な概念です。必要な分だけ通信が発生するので大変無駄がありません。昨今のSPAの多くが似た様な実装をしています。

テストを書いたり、VuetifyでUIを改善したり、バックエンドでより複雑な処理を実装してみたりとやるべきことはまだまだたくさん残っているので、そちらも挑戦してみたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA