Help us understand the problem. What is going on with this article?

RailsアプリにVue.jsを導入してみた(Vue.jsでRailsのDBを受け取る)

最近Vue.jsを勉強しはじめて、
なんとかRuby on Railsで書いた既存アプリのフロント周りをなんとかVue.jsで書き直してみたので自分用メモとして残しておきます。

今回の目標

vuejs.gif

画像のようにECサイト上でジャンル一覧から任意のジャンルをクリックすると、
RailsのDBから呼び出されたジャンルごとのアーティストが描画されるようにする!

概要

どうやってこれを実装するのか
RailsのデータベースをVue.jsで受け取るにはそのまま変数で渡すことはもちろん出来ません。
なので、RailsでAPIを作ってaxiosのgetメソッドでそこを叩いてVue側で受け取ることで繋がります。

まずVue.jsの導入

今回は既存のRailsアプリに後からVueを入れるやり方です。
Gemfileに

gem "webpacker", github: "rails/webpacker”

を追記してbundle installします。

そしてターミナルで以下のコマンドを

$ bin/rails webpacker:install

コンパイル

$ bin/webpack

でコンパイルしておきましょう

コンパイルが失敗したときは

development.rb
process.env.NODE_ENV = process.env.NODE_ENV || 'development'

const environment = require('./environment')

module.exports = Object.assign({}, environment.toWebpackConfig(), {
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    }
  }
})

をapp/config/development.rbに追記してください。

ここまででapp/javascript/packsというディレクトリが出来ているはずです。
今回はhello_vue.jsというファイルにコードを追記していきます。

Vueを読み込みましょう

application.html.erbのyieldの下に
を追加

application.html.erb
 <%= javascript_pack_tag "hello_vue" %>

APIの作成

今回hジャンルが選択されたら、そのジャンルのアーティストを配列で返すということをやりたいので、
Rails側のデータベースと連携させる必要があります。
なので

$ bundle exec rails g controller api::genres show

としてまずコントローラを作りましょう

ルーティングの追記

routes.rb
  namespace :api do 
    resources :genres, only: %i(show)
  end

API::GenresController

api/genres_controller
class GenresController < ApplicationController
  def show
    @genre = Genre.find(params[:id])
    @artists = Artist.where(genre_id: params[:id])
  end
end

ちなみにジャンルは複数のアーティストを持つので、
アソシエーションはGenre has_many artistsとなってます!

また、今回json形式で渡す必要があるのでjbuilderを使います。
app/views/api/genres/show.json.jbuilderに

show.json.jbuilder
json.genre_name @genre.genre_name
json.array do
  json.array! @genre.artists, :artist_name, :id
end

として、ジャンルごとのアーティスト一覧をarrayで渡しています。

APIの確認

/api/genres/1にアクセスすると
json.png
このようになっています。

ジャンルをクリックするたびにapi::genres_controllerが呼ばれて、クリックされたIDのジャンルがパラメータとして渡されています。

準備は整いました。

Vue.jsを書いていこう!

Vueのコード(hello_vue.js)

import Vue from 'vue/dist/vue.esm'
import axios from 'axios'

new Vue({
  el: ".genre_vue",
  data: {
    genreInfo: {},
    artists: [],
    showModal: false,
  },
  methods: {
    setGenreInfo(id){
      axios.get(`api/genres/${id}.json`)
      .then(res => {
        this.genreInfo = res.data;
        this.artists = res.data.array;
        this.showModal = true
      });
    },
    setArtistInfo(id){
     window.location.href = `artists/${id}`;
    }
  }
});

RailsのAPIからデータを持ってくるために冒頭でaxiosをimportしてます。
まずdataの中でartistsを空の配列で用意します。
axiosで自作APIからgenre別のartist配列を持ってきて、this.artistsに格納します。
setArtistInfoは無理やりアーティスト詳細ページにリンクを繋げたかっただけでもっといいやり方があるはずです。。

Railsのコード

<li v-for="artist in artists" v-on:click="setArtistInfo(artist.id)" class= "lime" v-bind:key="artist"> 
   {{ artist.artist_name }}
</li> 

先ほどVueの方でthis.artistsに格納された値をv-forディレクティブで回して
アーティストのアーティスト名をループさせています。

完成です!

次は検索機能を実装していきたいと思います。
現在は検索したらページ遷移させているのVueを用いて非同期で検索結果をレンダリングさせるようにします。

参照元

https://qiita.com/jnchito/items/30ab14ebf29b945559f6
https://qiita.com/cohki0305/items/582c0f5ed0750e60c951
https://qiita.com/cohki0305/items/a678b0b17c5b496c1de9

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away