せっかくdrinks/show.html.erbをapp.vueに記述しなおしたので、
モーダルウィンドウ的なものを実装したい。
つまり、投稿一覧から投稿を押すと、そのままapp.vueが画面遷移なしに表示されるとか
をやってみたい。
だけど、投稿一覧はerbで実装されてるので、そこからvueコンポーネントを表示できるのか。。。
https://qiita.com/t1gert1ger/items/b048a5fd81dc5a8fbfc8
自分がやりたいような記事はあった。
いや、てかやったことあったな。
application.html.erb
<%= javascript_pack_tag 'footer' %>
<template>
<div class="footer">
<div>
<router-link to="/contact">お問い合せ</router-link>
</div>
<div>
<router-link to="#">私たちについて</router-link>
</div>
<div>
<router-link to="#">コーヒーをもっと知る</router-link>
</div>
<div>
<router-link to="/about_coffee_passport">Coffee Passport とは</router-link>
</div>
</div>
</template>
import Vue from 'vue/dist/vue.esm.js'
import Router from './router/router'
import footer from './components/footer.vue'
var app = new Vue({
router: Router,
el: '#footer',
components: {
'navbar': footer,
}
});
import Vue from 'vue/dist/vue.esm.js'
import VueRouter from 'vue-router'
import Contact from '../components/contact.vue'
import About from '../components/about_coffee_passport.vue'
Vue.use(VueRouter)
export default new VueRouter({
mode: 'history',
routes: [
{ path: '/contact', component: Contact },
{ path: '/about_coffee_passport', component: About}
],
})
<template>
<div>
<form class="contact-form" action="https://formspree.io/f/xvovebqd" method="post">
<input type="hidden" name="_subject" value="お問い合せ" >
<input type="hidden" name="_next" value="https://www.youtube.com/" >
<label for="email"> メールアドレス</label>
<input name="Email" id="email" type="email" placeholder="coffee@gmail.com" required>
<label for="name">お名前</label>
<input type="name" placeholder="珈琲太郎" required>
<label for="context"> お問合わせ内容</label>
<textarea name="context" id="" cols="30" rows="10"></textarea>
<button class="contact-submit" type="submit">送信する</button>
</form>
</div>
</template>
こうすると、お問い合わせページが表示される。
ただこれは、router-linkで表示させていたので、erbにrouter-linkをつかえれば話はべつ。。。
もしくは、投稿一覧ページをvueで実装するか。。。って感じ。。。
ってことで、投稿一覧ページをvueで実装
namespace :api, format: 'json' do
resources :drinks, only: [:index,:show]
end
class Api::DrinksController < ApplicationController
include SessionsHelper
def index
def index
@user = current_user
following_ids = 'SELECT followed_id FROM relationships WHERE follower_id = :user_id'
@drinks = Drink.includes(:user ,{image_attachment: :blob})
.where.not(user_id: 6)
.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: @user.id)
.order('drinks.created_at DESC')
@random_drinks = Drink.includes(:user, {image_attachment: :blob}).order('RAND()').limit(5)
end
end
json.array! @drinks do |drink|
json.name drink.name
json.explain drink.explain
json.region_name drink.region.name
json.acidity_name drink.acidity.name
json.body_name drink.body.name
json.processing_name drink.processing.name
json.likes_count drink.likes_count
json.user_id drink.user_id
json.image rails_blob_url(drink.image) if drink.image.attached?
end
[{"name":"ddd","explain":"dddddd","region_name":"---","acidity_name":"---","body_name":"---","processing_name":"---","likes_count":1,"user_id":7,"image":"http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBGQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--a5cbc36b9182e1ffa204bbf8cf5678f1790eec3f/anastasiia-chepinska-lcfH0p6emhw-unsplash.jpg"},{"name":"SSS","explain":"ddddd","region_name":"---","acidity_name":"---","body_name":"---","processing_name":"---","likes_count":1,"user_id":7,"image":"http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBFdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--298eaaf8b1f1cd2a3d527cd25f42ee99cac79e9f/anastasiia-chepinska-lcfH0p6emhw-unsplash.jpg"},{"name":"aaaaa","explain":"#sssss","region_name":"ラテンアメリカ","acidity_name":"MEDIUM(ほどよい)","body_name":"LIGHT(軽い)","processing_name":"WASHED(水洗式)","likes_count":1,"user_id":7,"image":"http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBFZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--7c49e17b8aeaf1a37ad4fec0714d0b2b128225e5/anastasiia-chepinska-lcfH0p6emhw-unsplash.jpg"},{"name":"サンプル","explain":"#ああああ","region_name":"アジア、太平洋","acidity_name":"MEDIUM(ほどよい)","body_name":"LIGHT(軽い)","processing_name":"SEMI-WASHED(半水洗式)","likes_count":0,"user_id":7,"image":"http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBFUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--aeff59b28c839b85929e21719b4095174c835734/anastasiia-chepinska-lcfH0p6emhw-unsplash%20(1).jpg"}]
jsonデータを取ってくることができた!!
だがしかし、v-forでリストレンダリングしなければならないので、このような形式でいいのだろうか
結論大丈夫
いいね機能が上手く機能しなくなった。
投稿一覧でなにか一つの投稿にいいねしたあとに
リロードすると、全部の投稿にいいねがつくようになってしまった。
drink.idの受け渡しの方法を工夫したいと思う。
app.vue(投稿一覧)でdrink.idとやったらそれぞれと投稿が
親コンポーネントから子コンポーネントへ値を受け渡すことはできそう。
しかし、user_idが受け渡せない。
index.json.jbuilderに
json.user @user , :id
とかやっても、すでに
json.array! @drinks do |drink|
json.id drink.id
json.name drink.name
json.explain drink.explain
json.price drink.price
json.acidity_id drink.acidity_id
json.body_id drink.body_id
json.processing_id drink.processing_id
json.region_id drink.region_id
json.region_name drink.region.name
json.acidity_name drink.acidity.name
json.body_name drink.body.name
json.processing_name drink.processing.name
json.likes_count drink.likes_count
json.user_id drink.user_id
json.nickname drink.user.nickname
json.image rails_blob_url(drink.image) if drink.image.attached?
end
と書いてるから、できない。
cant add to an arrayとかいうエラーを出された。
そこらへん上手くやってくれよ。jsonsさんよ。。。
drinks/index.html.erbに
<script>
var user = <%= { id: current_user.try(:id) }.to_json.html_safe %>;
</script>
こうやってかけば、drinks#indexにcurrent_userは定義されてあるので、現在ログインしてるユーザーのidをvueに受け渡せる。
これはあまり良くない方法かもしれないが、現在ログインしてるユーザーのidはerbからvueに受け渡して、
投稿のidはapi:index_controller#indexで定義した@drinkから
jbuilderを介して受け渡してもらう
そして、app.vueにlikeButtonが子コンポーネントとして表示されているので、
app.vueに受け渡されたjsonデータを子コンポーネントのlikeButton.vueに受け渡したい
親コンポーネントから子コンポーネントへデータの受け渡し
<likeButton :drinkId=drink.id></likeButton>
props: ["drinkId"],
と記述して、this.drinkIdとかやればアクセスできる。
こうやってやったら、投稿一覧ページからでもいいね機能が機能するようになりました!!
次回は,drink/show.vueをモーダルや、router-viewとかで表示させていきたいとおもいます!!