Rails × Vue.jsでカルーセルを実装

https://ssense.github.io/vue-carousel/
カルーセルとはこんな感じ。

これを実装していく。
トップページのログインページにこれを表示させたいので、

#自作vueコンポーネントをerbに表示させる

```erb



<div class="top-explain">
  <div class="app-title">
    <%= image_tag 'coffee_gif.gif' ,class: "coffee-gif"%>
    <div class="app-text">
      <h3 class="top-explain-title" >Von Voyage!</h3>
      <p class="app-concept">Coffee Passportとはあなたが出会ったコーヒーの記録を共有できるサービスです</p>
    </div>
  </div>
  

    <div class="explain-wrapper">
    <ruby>
      <h3 class="explain-wrapper-title">出会ったコーヒーをシェアしよう</h3>
      <rt class="explain-wrapper-title-en">share your favorite coffee</rt>
    </ruby>


      <p class="explain-wrapper-info">
      出会ったコーヒーの感想を記録して共有しましょう。
      その投稿が、素敵なコーヒーを求めてる誰かのヒントになるでしょう。
      </p>
      <%= image_tag 'post.png',class: "explain-post-img"%>
      
    </div>
    <div class="explain-wrapper">
    <ruby>
      <h3 class="explain-wrapper-title">コーヒーを探す旅へ</h3>
      <rt class="explain-wrapper-title-en">vayage to find coffee</rt>    
    </ruby>

      <p class="explain-wrapper-info">
      お気に入りのコーヒーに出会いたいときは、検索してみましょう。
      コーヒーの名前、コク、酸味、産地、加工法などで検索できます。
      </p>
    </div>
    <div class="explain-wrapper">
    <ruby>
      <h3 class="explain-wrapper-title">素敵なコーヒーがあなたの手元に</h3>
      <rt class="explain-wrapper-title-en">special coffee will come to your house</rt>    
    </ruby>


      <p class="explain-wrapper-info">
        コーヒーを家でも楽しみたいなら、素敵なコーヒーのラインナップを
        取り揃えておりますので、ぜひお求めください。
      </p>
    </div>
     <div class="explain-wrapper">
     <ruby>
      <h3 class="explain-wrapper-title">いいねやコメントで盛り上がろう</h3>
      <rt class="explain-wrapper-title-en">smash that like button and comment </rt>
     </ruby>


      <p class="explain-wrapper-info">
        気に入った投稿に「いいね」を押したり、コメントして
        一杯のコーヒーが生み出すコミュニティに参加しましょう。
      </p>
    </div>   
</div>




<% provide(:title,"Login")%>
<div class="slideshow">
<%= form_with(url: login_path, scope: :session,class: 'registration-main', local: true) do |f| %>

<div class='form-wrap'>
  <div class='form-header'>
    <p class='form-header-text'>
      ログインしてコーヒーの旅へ出かけよう
    </p>
  </div>
   <% flash.each do |message_type, message| %>
    <div class="alert-<%= message_type %>">
      <%= message%>
    </div>
  <% end %>

 
  <div class="form-group">
    <p class="please-checking">
        新しく新規登録した場合は<br>
        メールボックスに承認用のメールが<br>
        届いてるかご確認ください
    </p>
    <div class='form-text-wrap'>
      <%# <label class="form-text">メールアドレス</label>
      <span class="indispensable">必須</span> %>
    </div>
    <%= f.email_field :email, class:"input-default", id:"email", placeholder:"メールアドレス", autofocus: true %>
  </div>
  <div class="form-group">
    <div class='form-text-wrap'>
      <%# <label class="form-text">パスワード</label>
      <span class="indispensable">必須</span> %>
    </div>
    <%= f.password_field :password, class:"input-default", id:"password", placeholder:"パスワード" %>
  </div>
  <div class='login-btn'>
    <%= f.submit "ログイン" ,class:"login-red-btn" %>
  </div>
  
  <div class="signin">
    <%= link_to "ゲストログイン", users_guest_sign_in_path, method: :post,class: "guest_login"%>
    <p>アカウントをお持ちでないですか？</p>
    <%=link_to "登録する",new_user_path, class: "signin-path"%>
  </div>
</div>


<% end %>
<%#= link_to "Googleアカウントでログイン", "/users/auth/google_oauth2/callback",method: :post %>
<%#= link_to "Facebookアカウントでログイン", "/auth/facebook" %>
</div>

```

ログインフォームはrailsのerbのままで、説明ページはvueで実装して、カルーセルをやりたい。。。


まずは、app/javascript/packs/appExplain.js

app/javascript/packs/components/static_pages/appExplain.vue

を作成。んでこのあとどうすんだっけな。。。


vue テンプレートを erbに表示させたい。

```erb
<%= javascript_pack_tag 'hello_vue' %>

```

```hello_vue.js
import Vue from 'vue'
import App from '../app.vue'
import VModal from 'vue-js-modal'
import VueYoutube from 'vue-youtube'
Vue.use(VueYoutube)
Vue.use(VModal)
Vue.config.devtools = true;

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)

  console.log(app)
})

```

ってやって,app.vueを表示させてたんよねぇ。。


やっぱ名前をappExample.jsからapp_example.jsに変える


```new.html.erb
<%= javascript_pack_tag 'app_example' %>
```

```app_explain.js

import Vue from 'vue'
import appExplain from '../packs/components/static_pages/appExplain.vue'

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    render: h => h(appExplain)
  }).$mount()
  document.body.appendChild(app.$el)

  console.log(appExplain)
})
```

こんな感じのノリで書いてみる

Webpacker::Manifest::MissingEntryError in Sessions#new
とエラーが起きた。

```app_explain.js
import Vue from 'vue'
import appExplain from '../packs/components/static_pages/appExplain.vue'

var app = new Vue({
  el: '#app-explain',
  components: {
    'app-explain': appExplain,
  }
});
```

```erb

<div id="app-explain">
<app-explain></app-explain>
</div>
 <%= javascript_pack_tag 'app-explain' %>
```

こんな感じで表示

でも同じエラーでした。。。

hello_vueからapp.vueしか、表示させれないのか。。。

ただ、footerは確かvueで書いてたはず。。。


```footer.js

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,
  }
});


```

```erb:application.html.erb

    <footer id="footer">
     <router-view></router-view>
     <navbar></navbar>
     <%# vue.js側でこのタグとコンポーネントを紐付ける %>
      <%#= render 'shared/footer'%>
    </footer>

 <%= javascript_pack_tag 'footer' %>
```

と書いたのだが、、。。。

この書き方はrouter-viewを使うとき限定？？


```app_explain.js

import Vue from 'vue'
import appExplain from '../packs/components/static_pages/appExplain.vue'

document.addEventListener('DOMContentLoaded', () => {
  var app = new Vue({
    el: '#app-explain',
    components: {
      "app_explain": appExplain
    },
    render: h => h(appExplain)
  }).$mount()
  document.body.appendChild(app.$el)
})



```

上記の折衷案みたいな書き方をしてみる。

それでもエラー変わらず。
ローカル上でコンパイルとかする必要あったり。。。

てかhello_vueを介してapp.vueを表示させてる以外の記事がない。。。

```
soichirohara@SoichironoMacBook-Pro coffee_passport % docker-compose exec rails webpacker:compile
```

こんなコマンドを打って、コンパイルできるかどうか。。。

エラー変わらず

```
docker-compose  exec web rails webpacker:compile
```

こうやって打つべきだった。実行
したら、色々コンパイルされた。。。


エラーはなくなったが、
appExplain.vueが上手く表示されてない気がする。

undefined
﻿
login:42 GET http://localhost:3000/packs/js/application-a443a43….js net::ERR_ABORTED 404 (Not Found)
login:69 GET http://localhost:3000/packs/js/app_explain-f166883….js net::ERR_ABORTED 404 (Not Found)
login:119 GET http://localhost:3000/packs/js/footer-a150cd9….js net::ERR_ABORTED 404 (Not Found)
login:15 GET http://localhost:3000/js/jquery.bgswitcher.js net::ERR_ABORTED 404 (Not Found)
login:42 GET http://localhost:3000/packs/js/application-a443a43….js net::ERR_ABORTED 404 (Not Found)
login:69 GET http://localhost:3000/packs/js/app_explain-f166883….js net::ERR_ABORTED 404 (Not Found)
login:119 GET http://localhost:3000/packs/js/footer-a150cd9….js net::ERR_ABORTED 404 (Not Found)

検証ツールでこんなエラーが、、。。。
へえええ。。。
関係ないところまでなんかエラーになった。。。
ので一旦dockerを再起動！！

jqueryの方のエラーはなくなったが、
まだ、appExplainは表示されてない。。。



Failed to load resource: the server responded with a status of 404 (Not Found)

と表示されていた。。。

```app_explaine.js
import Vue from 'vue'
import appExplain from '../packs/components/static_pages/appExplain.vue'

document.addEventListener('DOMContentLoaded', () => {
  var app = new Vue({
    el: '#app-explain',
    components: {
      "app_explain": appExplain
    },
    render: h => h(appExplain)
  }).$mount()
  document.body.appendChild(appExplain.$el)
})


```

としたらいけた。

```app_explain.js
import Vue from 'vue'
import appExplain from '../packs/components/static_pages/appExplain.vue'

document.addEventListener('DOMContentLoaded', () => {
  var app = new Vue({
    el: '#app-explain',
    components: {
      "app_explain": appExplain
    },
    render: h => h(appExplain)
  }).$mount()
  document.body.appendChild(app.$el)
})
```


  document.body.appendChild(app.$el)
にしてたから上手くいかなかったみたい。。。

ほぼほぼ脳死のゴリ押しだったがよかった。。。

# 下準備ができたので、カルーセルを実装

```appExplain.vue

<template>
  


<div class="top-explain">
  <carousel :per-page="1"  autoplay=true  loop=true　 >
    <slide autoplayTimeout=1000>
      <div class="app-title">
          <img class="coffee-gif" :src="require('/public/assets/images/coffee_gif.gif')"> 
        <div class="app-text">
          <h3 class="top-explain-title" >Von Voyage!</h3>
          <p class="app-concept">Coffee Passportとはあなたが出会ったコーヒーの記録を共有できるサービスです</p>
        </div>
      </div>
    </slide>

    <slide autoplayTimeout=3000>
      <div class="explain-wrapper">
      <ruby>
        <h3 class="explain-wrapper-title">出会ったコーヒーをシェアしよう</h3>
        <rt class="explain-wrapper-title-en">share your favorite coffee</rt>
      </ruby>


        <p class="explain-wrapper-info">
        出会ったコーヒーの感想を記録して共有しましょう。
        その投稿が、素敵なコーヒーを求めてる誰かのヒントになるでしょう。
        </p>
        <img class="explain-post-img" :src="require('/public/assets/images/post.png')" >
      </div>
    </slide>


    <slide autoplayTimeout=3000>
        <div class="explain-wrapper">
        <ruby>
          <h3 class="explain-wrapper-title">コーヒーを探す旅へ</h3>
          <rt class="explain-wrapper-title-en">vayage to find coffee</rt>    
        </ruby>

        

          <p class="explain-wrapper-info">
          お気に入りのコーヒーに出会いたいときは、検索してみましょう。
          コーヒーの名前、コク、酸味、産地、加工法などで検索できます。
          </p>
        </div>
    </slide>

    <slide autoplayTimeout=3000>
      <div class="explain-wrapper">
      <ruby>
        <h3 class="explain-wrapper-title">素敵なコーヒーがあなたの手元に</h3>
        <rt class="explain-wrapper-title-en">special coffee will come to your house</rt>    
      </ruby>
        <p class="explain-wrapper-info">
          コーヒーを家でも楽しみたいなら、素敵なコーヒーのラインナップを
          取り揃えておりますので、ぜひお求めください。
        </p>
      </div>
    </slide>



    <slide>
        <div class="explain-wrapper">
        <ruby>
          <h3 class="explain-wrapper-title">いいねやコメントで盛り上がろう</h3>
          <rt class="explain-wrapper-title-en">smash that like button and comment </rt>
        </ruby>


          <p class="explain-wrapper-info">
            気に入った投稿に「いいね」を押したり、コメントして
            一杯のコーヒーが生み出すコミュニティに参加しましょう。
          </p>
        </div>   
    </slide>

  </carousel>

</div>
</template>

<script>
import { Carousel, Slide } from 'vue-carousel';
export default {
  components: {
    Carousel,
    Slide
  }
}
</script>
```

こんな感じでかいたらおけ。
https://github.com/SSENSE/vue-carousel
色々なオプションとかは、公式githubまで。

ちなみに画像の表示のさせ方が若干苦労した。
assetsに置いてある画像をそのまま読み込むやり方もあったそうだが、なんか上手くいかなかったので、
publicディレクトリに置いて、こんな感じに書いたらいけました。

```app.vue
 <img class="coffee-gif" :src="require('/public/assets/images/coffee_gif.gif')"> 

```