🐵

SPAをRailsとvue.jsとDRFで作成する

2022/05/09に公開

はじめに

django rest frameworkでapiを作り, それを使用したSPAをruby on railsで作成します。

apiは下から2番目の項目 ソースにある「djangoのプロジェクト」
今回作成するSPAは 「railsのプロジェクト」になります。詰まった時の参考にどうぞ。

開発環境

  • OS: macOS Big Sur v11.5.2
  • Python: Python 3.0.6
  • Django: 3.2.5
  • ruby:2.6.5
  • Rails: 6.1.4.1

Djangoのプロジェクトを作成

別のプロジェクトとしてdjangoでAPIを実装

下から2番目の項目にあるソースにあるように「djangoのプロジェクト」を作成します。
下の2つの記事を行うことで作成します。

API実装

Django REST Frameworkを使って爆速でAPIを実装する

CORS設定

DRFを使って、APIエンドポイントをフロントエンドから叩く場合にはCORSの設定が必要

【drf】django-cors-headersを使ってCORS設定を行う

動作確認


# 開発サーバーを起動
$python manage.py runserver

http://localhost:8000/admin/
管理画面に入り,EntrysとUsersをいくつか作っておく



http://localhost:8000/api/entries/
でEntryの情報を受け取れるか確認


railsのプロジェクトを作成

別のプロジェクトとしてrailsでSPAを実装

#spaディレクトリにrailsプロジェクトを作成
$rails new spa

# spaディレクトリに移動
$cd spa

# 開発サーバーの起動
$rails s

動作確認

https://localhost:3000
サーバが立ち上がることを確認する



コントローラーとビューを作成

#topコントローラー(top_controller.rb)とビュー(show.html.erb)を作成
$rails g controller top show

$rails g controller top showでtopコントローラ-とビューを作成し,ルーティングとアクション追加までしてくれます

コントローラーの確認

top_controller.rb

class TopController < ApplicationController
  def show
  end
end

$rails g controller top showでshowアクションは自動で定義されるが一応のため確認.

showアクションが実行されると, app/views/top/show.html.erbを探して表示してくれる

ルーティングを定義

routes.rb

Rails.application.routes.draw do
  get "", to: "top#show"
end

https://localhost:3000/
でtopコントローラのshowアクションが呼び出し,show.html.erbを表示できるようにした

ビューをを編集

show.html.erb


<h2>HelloWorld</h2>

HelloWorldを表示させるようにする

動作確認

#開発サーバーの起動
$rails s

https://localhost:3000
show.html.erbが表示されることを確認



HelloWorldが表示されたらOK

vue.js環境構築

vueをインストール

#vue.js環境構築
$bundle exec rails webpacker:install:vue

vue.jsを利用するにあたり必要なファイルを用意してくれます。

ビューを編集

show.html.erb

<%= javascript_pack_tag 'hello_vue' %>
<%= stylesheet_pack_tag 'hello_vue' %>

動作確認

$bundle exec rails s

https://localhost:3000
「Hello Vue!!」と表示されていれば、環境構築は完了です。



APIを使用したSPAを作成する

axiosをインストール

#axiosをインストール
$yarn add axios

ビューを編集

app/views/top/show.html.erb

<%= javascript_pack_tag 'api' %>
<%= stylesheet_pack_tag 'api' %>

<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>

<div class="my-container">
    <div class="container" id="app">
        <div class="content">
            <div>
                <span class="index">タイトル</span><span>{{django.data.title}}</span>
            </div>
            <div class="blank">
                <span class="index">本文</span><span>{{django.data.body}}</span>
            </div>
            <div>
                <span class="index">名前</span><span>{{django.data.author.name}}</span>
            </div>
            <div class="blank">
                <span class="index">メール</span><span>{{django.data.author.mail}}</span>
            </div>
            <select @click="search" v-model="section">
                <option v-for="section in sections" :value="section">{{ section }}</option>
            </select>
            <br>
            <button class="btn btn-primary" type="submit" @click="active">データを取得</button>
        </div>
    </div>
</div>

Bootstrapを使用しています.

<%= javascript_pack_tag 'api' %> <%= stylesheet_pack_tag 'api' %>でapp/javascript/packs/api.jsを読み込んでいます.

v-model="section"より, セレクトボックスは双方向にバインディングしています.

v-for="section in sections" :value="section"より, sections配列に格納されている値一つ一つをvalueとして選択できるようなセレクトボックスのoptionを作っています.

@click="search"より,クリックされた時にsearch関数が呼び出されます.

同様に, ボタンは@click="active"より,クリックされた時にactive関数が呼び出されます.


axiosを使用

app/javascript/packs/api.jsを作成


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

document.addEventListener('DOMContentLoaded', () => {
const vm = new Vue({
    el: '#app',
    data() {
      return {
        sections:["1","2","3","4","5","6"],
        section: "1",
        django:null,
        url :"http://localhost:8000/api/entries/1/?format=json",
        lead_url:"http://localhost:8000/api/entries/",
        behind_url:"/?format=json",
      }
    },
    methods: {
      active: function () {
          this.url = this.lead_url + this.section + this.behind_url;
          axios.get(this.url)
          .then(response => {this.django = response})
      },
      search: function() {
        this.url = this.lead_url + this.section + this.behind_url;
      }
  },
    mounted() {
      axios.get(this.url)
      .then(response => {this.django = response})
    },
  })

})

「情報を取得する」 ボタンが押された時に実行されるactive関数では,セレクトボックスにセットされている取得したいEntryのidsectionを,HTTPメソッドを格納する変数urlに埋め込み,そのHTTPメソッドでAPIと通信を行い, データを取得しています.

axios.get(this.url)で, HTTPメソッドを実行し, APIと通信を行う.

必要とする情報はAPIからのレスポンスの中にある.

.then(response => {this.django = response})で, this.djangoにAPIからのレスポンスであるJSONデータを取得.

show.html.erbで{{django.data.title}}{{django}}などとすることでapp.jsで宣言や取得した値を表示させることができる.

とりあえず1~6番目に作成したEntryを取得できるようにsections:["1","2","3","4","5","6"]としました

任意で減らしたり増やしたり,取得したいEntryのidに変えてください


デザインを適用

app/assets/stylesheets/top.scss




.my-container {
    width: 400px;
    height: 400px;
    margin: auto;
    background-color: #dbdbd9;
    margin-top: 200px;

    select {
        width: 100px;
        margin: 20px;
    }

    .content {
        display: inline-block;
        margin: auto;
        margin-top: 40px;

        span.index {
            display: inline-block;
            padding: 3px;
            border-radius: 5px;
            background-color: #007bff;
            color: white;
            margin-bottom: 10px;
            margin-right: 10px;

        }


    }
}

デザインは好みでお願いします


動作確認

$bundle exec rails s

https://localhost:3000



selectボタンで取得したいEntryの番号を選択し, データを取得を押すとAPIからデータを取得することができる


SPA完成!!

GETしかできないが,他も実装予定

何も表示されない場合はdjangoのサーバが起動しているか確認したり, 検証でエラーを確認

ソース

djangoのプロジェクト


#django_rest_frameworkディレクトリに移動
$cd django_rest_framework

#マイグレーションファイルをもとにデータベースを作成
$python manage.py migrate

#django-cors-headersをインストール
$pip install django-cors-headers

#Userを作成
$python manage.py createsuperuser

#サーバーの起動
$python manage.py runserver

railsのプロジェクト

#SPAディレクトリに移動
$cd SPA

#gemをインストール
$bundle install

#vueをインストール
$bundle exec rails webpacker:install:vue

#axiosをインストール
$yarn add axios

#サーバーの起動
$rails s

上記を実行してください

参考URL

Discussion