Rails6でMaterialize.cssのDatepickerを使いたい！

初めまして、ゆん♂です！
不動産業界に激震を走らせるためのアプリを作ってます！

どうせ作るなら最新の環境で作りたい！ということで `Rails6系` でアプリ制作してます。

が！ `Rails5系` と `Rails6系` では大きく仕様が異なっており、表題のような簡単なことでも超絶つまづいてしまいました。
解決してみたら何のことはなかったんですが、僕はこれだけで丸1日溶けました…。
なので同じ轍を踏まないよう、僕の試行錯誤の軌跡をここに残しておきます。

長ったらしい話はいいからさっさと結果だけよこせや、って方は[こちらへどうぞ！](https://qiita.com/TechTech_Walk/items/84d5fc0f6af208929d3f#%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%81%A7%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%93%E3%82%8C%E3%81%8C%E6%AD%A3%E8%A7%A3)

# 開発環境

言語: `Ruby2.6.6`
フレームワーク: `Rails6.0.3.4`
データベース: `MySQL（ローカル）`
IDE: `VScode`

# Rails6ってなんかカッコイイ！！

これは `Rails6` を採択した理由です。マジです。
`Rails6`って何か響きだけでカッコ良くないですか！？
しかも5よりも6のほうが新しいし、古いバージョンで作って早々バージョンアップデートとか必要になったら二度手間！
（↑これは多分正しい、、、はず）
という安直な理由で `Rails6` を採択しました。

このあと地獄を見るとも知らずに、、、

# Materialize.cssのDatepickerオシャレ！！

ちょっと見てください[コレ](https://materializecss.com/pickers.html)。
めちゃくちゃオシャレじゃないですか？？
`CSS` 全く書かずにこんなUIが実現できるなんて便利な世の中ですよねほんと☺️

![スクリーンショット 2021-01-05 14.55.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908918/d80af6dc-7bb4-da7c-a6b1-8edf990077ef.png)

で、このドキュメントには
「カレンダー表示させたい `inputタグ` に `datepicker` というクラス名を付けてな」
「あとは `JavaScript` か `jQuery` でちょちょいと書いたら終わりやで」
と書いてあります。オージーザス、神よありがとう🙏

# gem じゃなくて webpacker！！

`Datepicker` を使うには `jQuery` を入れておいた方が良さそうです。
`Rails5系` だと `gem` でインストールして `CSS` や `JS` で読み込ませてねー的な記事がたくさん出てくるのですが、`Rails6系` では JavaScript系のパッケージ機能を `gem` ではなく `webpacker` で管理するようになったそうです！

>Webpackerとは、 Webpackを使用してRuby on Rails上でJavaScript開発をするために必要な一連のまとまりを、標準で実装することができるgemパッケージ です。 Rails6.0より、webpackerが標準実装になりました。

参照： [【基本】webpackerとは何か学ぼう](http://it-kyujin.jp/article/detail/1661/)

なんてこったパンナコッタ！！

オーマイゴッドファーザー降臨！よいしょ！

こりゃ便利！！、、、、、なのでしょうか🤔？？

この辺り実はメリデメがよく分かっていません。
んー、あいまいみーまいん🙁

まぁ正確な理解は置いておいて、`Rails6 jQuery` で調べると必ずと言っていいほど `webpacker` で管理しましょうねーという記事が出てきます。
というかそんな記事しかありません！
（↑それ自体は多分正しい）
併せて `jquery-ui-dist` なるものもインストールする必要があるようです。

**以下、参考にした記事**
[Rails6でjQueryの導入方法](https://qiita.com/masahisa/items/eaacb0c3b82f4a11fc13)
[【Rails6】jQueryがなかなか使い始められない人へ](https://qiita.com/iiyama_makoto/items/940b130fd20540fd70f1)
[【Rails6】Webpackerを用いてjQueryをインストールする手順を簡単にまとめてみた](https://techtechmedia.com/jquery-webpacker-rails/)
[Rails 6:webpackerを介してjquery-uiを追加する方法は？](https://python5.com/q/fulxlsen)

実はこの時すでに術中にハマってました。
js系のパッ毛0時は必ず `webpacker` で管理しなければならないと思い込んでいたのです。
そのため、 `rails6 webpacker datepicker` とか `webpacker jquery-ui-dist` などと調べていたため、余計にドツボにハマる結果となりました。

`パッ毛0時` て何やねん、`パッケージ` やろがい。

# 丸1日かけてやったこと（間違い）

リアルに丸1日ハマり倒した内容を簡潔に書いていきます。
間違ってもこの手順を踏まないでください。
あくまでも同じ過ちを犯さないで欲しいがためのメモです。
**これは誤った手順です！**

## ① Yarnで `jQuery` と `jquery-ui-dist` をインストール

```terminal
$ yarn add jquery
$ yarn add jquery-ui-dist
```
↑ターミナルでこのコマンドを実行しました。

## ② `jQuery` と `jquery-ui-dist` を有効化

```config/webpack/environment.js
const { environment } = require('@rails/webpacker')

// 追加ここから //////////////////////////////////////////
const webpack = require('webpack')
environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery'
  })
);

const aliasConfig = {
  'jquery': 'jquery-ui-dist/external/jquery/jquery.js',
  'jquery-ui': 'jquery-ui-dist/jquery-ui.js'
};

environment.config.set('resolve.alias', aliasConfig);
// 追加ここまで //////////////////////////////////////////

module.exports = environment

```

```app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

// 追加ここから //////////////////////////////////////////
global.$ = require("jquery")

require("jquery")
require("jquery-ui")
// 追加ここまで //////////////////////////////////////////
```

```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>ReTECH</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <!-- Compiled and minified CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <!-- Compiled and minified JavaScript -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <!-- Let browser know website is optimized for mobile -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <!-- Make FontAwesome available -->
    <script src="https://kit.fontawesome.com/xxxxxxxxxxx.js" crossorigin="anonymous"></script>

    <%= favicon_link_tag 'favicon.ico' %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_link_tag '//ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/le-frog/jquery-ui.min.css' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```
↑ 各ファイルにこのような記述を追加しました。
※ `app/views/layouts/application.html.erb` に関しては `Materialize.css` をCDN読み込みしてたりするので丸々掲載しました。`<script src="https://kit.fontawesome.com/xxxxxxxxxxx.js"` の `xxxxxxxxxxx.js` の部分は各自アカウントにより異なります。`FontAwesome` アカウント発行を自分で発行して適切な文字に置き換えてください。

参照: [Rails 6: How to add jquery-ui through webpacker?](https://stackoverflow.com/questions/57555708/rails-6-how-to-add-jquery-ui-through-webpacker)
参照: [FontAwesome6 無料登録](https://fontawesome.com/)

## ③ `datepicker` をフォームに適用してみる

```app/javascript/modules/datepicker.js
$(document).ready(function(){
  $('.datepicker').datepicker();
});
```
↑datepicker用jsファイルを定義

```app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

global.$ = require("jquery")
require("jquery")
require("jquery-ui")

// 追加ここから //////////////////////////////////////////
require("../modules/datepicker")
// 追加ここまで //////////////////////////////////////////
```
↑作ったdatepicker定義ファイルの読み込み

```app/views/devise/registrations/new.html.erb
<div class="input-field">
  <%= f.label :birthday %><br />
  <%= f.text_field :birthday, required: true, class: 'datepicker' %>
</div>
```
↑誕生日入力フォームに `datepicker` というクラス名を付与

# 出来上がったものがこちらです☺️

![スクリーンショット 2021-01-05 9.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908918/547d83d2-bc02-0842-3c5d-6e66ab75fbcf.png)

おい！

昔のiPhoneかよ！

一瞬電卓に見えたわ！

マテリアルの「マ」の字もないな！

作りたいのはこっち！！

![スクリーンショット 2021-01-05 14.55.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908918/ecabfb7b-3fd5-0e8f-4bdd-a278596254f4.png)

どれどれ、、、

![スクリーンショット 2021-01-05 9.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908918/3b8fee6c-711e-999f-80f7-b5685cba2a48.png)

電卓かて！！

# たぶん原因はこんな感じ

恐らく原因は CDNで `Materialize.css` を先に呼び出してしまい、そのあと `webpacker` の設定が読み込まれるため デフォルトの `datepicker` のUIで上書きされてしまっているのかなと推測しました。

ダメ元で `Materialize.css` のCDN呼び出しの記述をファイル後尾に移動したり、CDNではなく `CSSファイル` と `JSファイル` をダウンロードしてきて配置したりしました。

が、やはりダメ、、、

今までやったことは一応 `Github` でプルリク作って、もう一度やり直すことを決めました。。。

そして色んな試行錯誤を重ねた結果、こんな境地にたどり着いたのです。

# `jQuery` もCDNで呼び出せちゃったりしたりするかもなんじゃない？

そうです、何も `webpacker` で管理せず、`Materialize.css` と同じようにCDNで呼び出しちゃえばいいのでは？
そうすれば先に `jQuery` 呼び出して、後から `Materialize.css` を呼び出せる、、、UIを上書きされることもないはず！！

# ということでやってみた（これが正解）

```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>ReTECH</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <!-- Expressly read CDN to make jQuery available before make Materialize-UI available -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!-- Compiled and minified CSS -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <!-- Compiled and minified JavaScript -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
    <!-- Let browser know website is optimized for mobile -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <!-- Make FontAwesome available -->
    <script src="https://kit.fontawesome.com/xxxxxxxxxxxx.js" crossorigin="anonymous"></script>
    <%= favicon_link_tag 'favicon.ico' %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>
```
↑`<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>`という記述で `jQuery` を先に読み込み、そのあとに `Materialize.css` のCDNを読み込んでいる。

```app/javascript/modules/datepicker.js
$('document').ready(function() {
  $('.datepicker').datepicker();
})
```
↑datepicker定義

```app/javascript/packs/application.js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

// 追加ここから //////////////////////////////////////////
require("../modules/datepicker")
// 追加ここまで //////////////////////////////////////////
```
↑datepicker読み込み

```app/views/devise/registrations/new.html.erb
<div class="input-field">
  <%= f.label :birthday %><br />
  <%= f.text_field :birthday, required: true, class: 'datepicker' %>
</div>
```
↑誕生日入力フォームに `datepicker` というクラス名を付与

# 出来上がったものがこちらです😎

![スクリーンショット 2021-01-05 14.17.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/908918/4cbe5b87-32c0-0adf-4026-d9a845ba8e49.png)

完璧！！！

以上、長文にお付き合いいただきありがとうございました🙇‍♂️