商品をレビューできるようにしたいです
Rails×VueでSPA化されたサイトを作っているのですが
商品をレビューする機能を実装した際に、以下のようなエラーが発生しています
発生している問題・エラーメッセージ
createError.js:17 Uncaught (in promise) Error: Request failed with status code 404
該当のソースコード
Vue
1(DogfoodProductPage.vue) 2<template> 3<div class="top_contents"> 4<h2>詳細ページ</h2> 5<table> 6 <tbody> 7 <tr> 8 <th>登録ID</th> 9 <td>{{ dogfood.id }}</td> 10 </tr> 11 <tr> 12 <th>商品名</th> 13 <td>{{ dogfood.name }}</td> 14 </tr> 15 <tr> 16 <th>タンパク量</th> 17 <td>{{ dogfood.protein }}</td> 18 </tr> 19 <tr> 20 <th>脂肪量</th> 21 <td>{{ dogfood.fal }}</td> 22 </tr> 23 <tr> 24 <th>価格</th> 25 <td>{{ dogfood.price }}</td> 26 </tr> 27 </tbody> 28</table> 29 30<form @submit.prevent="createReview"> 31 <div> 32 <label>本文</label> 33 <input type='textarea' v-model='review.body'> 34 </div> 35 36 <button type="submit">コメント送信</button> 37</form> 38 39<ul> 40 <li v-for="review in reviews"> 41 {{ review.body }} 42 </li> 43</ul> 44 45 46</div> 47</template> 48 49<script> 50import axios from 'axios'; 51axios.defaults.headers.common = { 52 'X-Requested-With': 'XMLHttpRequest', 53 'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content') 54}; 55 56export default { 57 data: function () { 58 return { 59 review: { 60 body: '' 61 }, 62 reviews: [], 63 dogfood: [], 64 } 65 }, 66 methods: { 67 createReview: function() { 68 axios 69 .post('/api/v1/reviews', this.review) 70 .then(response => (this.info = response)) 71 }, 72 getReviews: function() { 73 axios 74 .get('/api/v1/reviews.json') 75 .then(response => { 76 for(var i = 0; i < response.data.reviews.length; i++) { 77 this.reviews.push(response.data.reviews[i]) 78 } 79 }) 80 } 81 }, 82 mounted : function() { 83 axios 84 .get(`/api/v1/sdogfoods/${this.$route.params.id}.json`) 85 .then(response => (this.dogfood = response.data)) 86 .catch(error => { 87 console.error(error); 88 if (error.response.data && error.response.data.errors) { 89 this.errors = error.response.data.errors; 90 } 91 }); 92 this.getReviews() 93 } 94} 95</script> 96 97<style scoped> 98</style>
Rails
1(reviews.controller) 2class Api::V1::ReviewsController < ApiController 3 4 def index 5 dogfood = Dogfood.find(params[:dogfood_id]) 6 reviews = dogfood.reviews.order('created_at DESC') 7 render json: reviews 8 end 9 10 def create 11 @review = Review.new(review_params) 12 if @review.save 13 render :index, status: :created 14 else 15 render json: @review.errors, status: :unprocessable_entity 16 end 17 end 18 19 private 20 21 def review_params 22 params.require(:review).permit(:dogfood_id, :body) 23 end 24end
rails
1(sdogfood_controller.rb) 2class Api::V1::SdogfoodsController < ApiController 3 before_action :set_dogfood, only: [:show] 4 5 def index 6 dogfoods = Dogfood.select(:id, :name, :protein, :fal, :price) 7 render json: dogfoods 8 end 9 10 def show 11 render json: @dogfood 12 end 13 14 private 15 16 def set_dogfood 17 @dogfood = Dogfood.find(params[:id]) 18 end 19end
Rails
1(review.rb) 2class Review < ApplicationRecord 3 belongs_to :dogfood 4end
Rails
1(dogfood.rb) 2class Dogfood < ApplicationRecord 3 has_many :reviews 4end
(route.rb) Rails.application.routes.draw do root to: 'home#index' (省略) namespace :api, {format: 'json'} do namespace :v1 do resources :sdogfoods, only: [:index, :show] resources :reviews, except: [:update] end end end
試したこと
this.getReviews()のコードを消せばエラーは消えるので、現在表示されているエラーは、getReviewsのaxiosが原因だと考えています。
(追記)
reviews.contorollerの、以下のコードに問題があると判明しました。
def index dogfood = Dogfood.find(params[:dogfood_id]) (省略) end
params[:dogfood_id]で、IDを取得できていないのでエラーが発生していたようです。
ならばと思い、(sdogfood_controller.rb)のshowアクションを、以下のように変更してみたのですが、render jsonを2つ記載すると、元々のrender json: @dogfoodが機能しなくなってしまい、別の問題で悩んでいます。
rails
1(sdogfood_controller.rb) 2class Api::V1::SdogfoodsController < ApiController 3 before_action :set_dogfood, only: [:show] 4 5 def index 6 dogfoods = Dogfood.select(:id, :name, :protein, :fal, :price) 7 render json: dogfoods 8 end 9 10 def show 11 @reviews = @dogfood.reviews.order('created_at DESC') 12 render json: @dogfood 13 render json: @reviews 14 end 15 16 private 17 18 def set_dogfood 19 @dogfood = Dogfood.find(params[:id]) 20 end 21end
現在は、問題を解決するために
- review_controller内で、dogfoodのIDを入手する
- render jsonを複数遅れるようにする
上記の方法のどちらかで、上手くいく方法がないか調べているところです。
もし、何か分かる方がいましたら、アドバイスをいただけると助かります。
※createReviewも、送信したら以下のエラーが出ますが、まずgetReviesのエラーを解決しようと思い、一旦createReviewは放置している状態です
Uncaught (in promise) Error: Request failed with status code 422
補足情報
Rails 6.0.3.5
上記のコードは、以下のようなコードで表示させています。
Rails
1(index.erb.html) 2<% provide(:title, "ドッグフードナビ") %> 3<%= javascript_pack_tag 'hello_vue' %>
JavaScript
1(hello_vue.js) 2import Vue from 'vue' 3import App from '../app.vue' 4 5document.addEventListener('DOMContentLoaded', () => { 6 const el = document.body.appendChild(document.createElement('hello')) 7 const app = new Vue({ 8 el, 9 render: h => h(App) 10 }) 11})
Vue
1(app.vue) 2<template> 3 <div> 4 <router-view></router-view> 5 </div> 6</template> 7 8<script> 9import Vue from 'vue' 10import VueRouter from 'vue-router' 11 12import DogfoodTopPage from 'DogfoodTopPage.vue' 13import DogfoodProductPage from 'DogfoodProductPage.vue' 14 15const router = new VueRouter({ 16 mode: 'history', 17 base: process.env.BASE_URL, 18 routes: [ 19 { path: '/', 20 component: DogfoodTopPage }, 21 { path: '/sdogfoods/:id(\d+)', 22 name: 'DogfoodProductPage', 23 component: DogfoodProductPage } 24 ] 25}) 26 27Vue.use(VueRouter) 28 29export default { 30 router 31} 32</script> 33 34<style scoped> 35</style>
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。