質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • Ruby on Rails

    8872questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • Vue.js

    1324questions

    Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Rails で Vueを使ってTrello風のアプリを作りたい

受付中

回答 0

投稿

  • 評価
  • クリップ 1
  • VIEW 49

前提・実現したいこと

RailsでVue.jsを使い、Trello風のアプリを作りたいと思っています。
Board、List、Cardをそれぞれ1対多で関連づけし、viewに表示したいです。
しかしVueを使うのが初めてでデータの受け渡しがよくわかりません。

発生している問題・エラーメッセージ

Vueで上記の親モデルから子モデルのデータを取得することができず困っています。
BoardShowページでboard_idに紐づいたList(list#index)、
Listではlist_idに紐づいたCard(card#index)を読み込みたいです。

ひとまずBoardShowでListを表示できるようにしたいです。

該当のソースコード

bord.rb

class Board < ApplicationRecord
  has_many :lists
end
list.rb

class List < ApplicationRecord
  acts_as_list
  belongs_to :board
  has_many :cards, ->{ order(position: :asc) }, dependent: :destroy
  scope :sorted, ->{ order(position: :asc) }

  validates :name, presence: true
end
card.rb

class Card < ApplicationRecord
  acts_as_list scope: :list
  belongs_to :list

  validates :name, presence: true
end
board_controller

class Api::BoardsController < ApplicationController
  before_action :set_board, only: [:show, :edit, :update, :destroy]

  def index
    boards = Board.all
    render json: boards
  end

  def show
    render json: @board
  end

  def new
    @board = Board.new
  end

  def create
    @board = Board.new(board_params)
    respond_to do |format|
      if @board.save
        format.html { redirect_to @board, notice: 'ボードを作成しました' }
        format.json { render :show, status: :created, location: @board }
      else
        format.html { render :new }
        format.json { render json:@board.errors, status: :unprocessable_entity }
      end
    end
  end

  def edit
  end

  def update
    respond_to do |format|
      if @board.update(board_params)
        format.html { redirect_to @board, notice: 'ボードを更新しました' }
        format.json { render :show, status: :ok, location: @board }
      else
        format.html { render :edit }
        format.json { render json:@board.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @board.destroy
    respond_to do |format|
      format.html { redirect_to boards_url, notice: 'ボードを削除しました' }
      format.json { head :no_content }
    end
  end

  private

  def set_board
    @board = Board.find(params[:id])
  end

  def board_params
    params.require(:board).permit(:name, :about)
  end
end
lists_controller

class Api::ListsController < ApplicationController
  before_action :set_list, only: [:show, :edit, :update, :destroy, :move]

  def index
    @board = board.find(params[:board_id])
    lists = @board.lists.sorted
    render json: lists
  end

  def show
    render json: @list
  end

  def new
    @list = List.new
  end

  def create
    @list = List.new(list_params)
    respond_to do |format|
      if @list.save
        format.html{ redirect_to @list, notice: 'リストを作成しました' }
        format.json{ render :show, status: :created, location: @list }
      else
        format.html{ render :new }
        format.json{ render json: @list.errors, status: :unprocessable_entity }
      end
    end
  end

  def edit
  end

  def update
    respond_to do |format|
      if @list.update(list_params)
        format.html{ redirect_to @list, notice: 'リストを更新しました' }
        format.json{ render :show, status: :ok, location: @list }
      else
        format.html{ render :edit }
        format.json{ render json: @list.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @list.destroy
    respond_to do |format|
      format.html{ redirect_to lists_url, notice: 'リストを削除しました' }
      format.json{ head :no_content }
    end
  end

  def move
    @list.insert_at(list_params[:position].to_i)
    render action: :show
  end

  private

  def set_list
    @list = List.find(params[:id])
  end

  def list_params
    params.require(:list).permit(:name, :position).merge(board_id: params[:board_id])
  end
end
cards_controller

class Api::CardsController < ApplicationController
  before_action :set_card, only: [:show, :edit, :update, :destroy, :move]

  def index
    @list = List.find(params[:list_id])
    cards = @list.cards.all
    render json: cards
  end

  def show
    render json: @card
  end

  def new
    @card = Card.new
  end

  def create
    @card = Card.new(card_params)
    respond_to do |format|
      if @card.save
        format.html { redirect_to @card, notice: 'カードを作成しました' }
        format.json { render :show, status: :created, location: @card }
      else
        format.html { render :new }
        format.json { render json:@card.errors, status: :unprocessable_entity }
      end
    end
  end

  def edit
  end

  def update
    respond_to do |format|
      if @card.update(card_params)
        format.html { redirect_to @card, notice: 'カードを更新しました' }
        format.json { render :show, status: :ok, location: @card }
      else
        format.html { render :edit }
        format.json { render json:@card.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @card.destroy
    respond_to do |format|
      format.html { redirect_to cards_url, notice: 'カードを削除しました' }
      format.json { head :no_content }
    end
  end

  def move
    @card.insert_at(card_params[:position].to_i)
    render action: :show
  end

  private

  def set_card
    @card = Card.find(params[:id])
  end

  def card_params
    params.require(:card).permit(:name, :about, :deadline, :position).merge(list_id: params[:list_id])
  end
end
app.vue

<template>
  <div id="app">
    <navbar></navbar>
    <router-view></router-view>
  </div>
</template>

<script>
import Vue from 'vue'
import axios from 'axios'
import VueRouter from 'vue-router'
import navbar from './packs/components/navbar.vue'
import BoardIndex from './packs/components/BoardIndex.vue'
import BoardShow from './packs/components/BoardShow.vue'

const router = new VueRouter({
  routes: [
    { path: '/', component: BoardIndex },
    { path: '/boards/:id(\\d+)',name: 'BoardShow', component: BoardShow }
  ]
})

Vue.use(VueRouter)

export default {
  router,
  name: 'App',
  components: { navbar },
}
</script>

<style scoped>
</style>
BoardShow.vue

<template>
  <div class="board">
    <p>{{ board.name }}</p>
    <draggable v-model="board.lists" group=".lists" class="dragArea d-inline-block" @end="listMoved">
      <list v-for="(list, index) in board.lists" :key="list.id" :list="list" :board="board" class="col-3">
      </list>
    </draggable>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import list from './List.vue'
import axios from 'axios'

export default {
  components: { draggable, list },
  props: ['board'],

  data: function() {
    return {
      board: {}
    }
  },
  mounted () {
    axios
      .get(`/api/boards/${this.$route.params.id}.json`)
      .then(response => (this.board = response.data))
  },
  methods: {
    listMoved: function(event) {
      var data = new FormData
      data.append("list[position]", event.newIndex +1)
      axios
        .patch(`/api/lists/${this.lists[event.newIndex].id}/move`)
        .then(response => (this.lists = response.data))
    }
  }
}

</script>
List.vue

<template>
  <div class="list">
    <div v-for="list in lists" :key="list.id">
      <p>{{ list.name }}</p>
    </div>
    <p>カード一覧</p>
  </div>
</template>

<script>
import draggable from 'vuedraggable'
import card from './Card.vue'
import axios from 'axios'

export default {
  components: { draggable, card },

  data: function() {
    return {
      lists: []
    }
  },
  mounted () {
    axios
      .get('/api/lists.json')
      .then(response => (this.lists = response.data))
  }
}

</script>
Card.vue

<template>
  <div>
    <div v-for="card in cards" :key="card.id">
      <p>{{ card.name }}</p>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data: function () {
    return {
      cards: []
    }
  },
  mounted () {
    axios
      .get('/api/cards.json')
      .then(response => (this.cards = response.data))
  }
}

</script>

Javascriptディレクトリファイル構成

javascript
├── packs
│           ├──components
│                           ├── BoardShow.vue
│                           ├── List.vue
│                           ├── Card.vue
│   
├── app.vue

補足情報(FW/ツールのバージョンなど)

Rails 5.2.3

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

同じタグがついた質問を見る

  • Ruby on Rails

    8872questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • Vue.js

    1324questions

    Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。