Rails でつくる fullcalendar

`fullcalendar` を実装することにした

https://github.com/bokmann/fullcalendar-rails

https://qiita.com/d0ne1s/items/fecd8dca4d34e005ce6d

https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0

https://qiita.com/syukan3/items/68280ce4ff45aa336363

上の記事参考にさせていただく

結果的にはこんなふう

[![Image from Gyazo](https://i.gyazo.com/add77d3cd4327c69c56850b0166dfb1f.png)](https://gyazo.com/add77d3cd4327c69c56850b0166dfb1f)

神社の参拝した日付と詳細がラベルになっている
それぞれラベルの部分を選択すると詳細にいく

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 前提
日付の入ったテーブルがある

## 本題

まずは

```:Gemfile
gem 'fullcalendar-rails'
gem 'momentjs-rails'
```

を `bundle install`

```:application.js
//= require jquery/dist/jquery.js
//= require moment 
//= require fullcalendar 
```

で読み込む。`jquery` は `yarn` でインストールしてあるのそっちを指定した

`js` ファイルは

```:js
$(function () {
  // 画面遷移を検知
  $(document).on('turbolinks:load', function () {
      if ($('#calendar').length) {

          function Calendar() {
              return $('#calendar').fullCalendar({
              });
          }
          function clearCalendar() {
              $('#calendar').html('');
          }

          $(document).on('turbolinks:load', function () {
              Calendar();
          });
          $(document).on('turbolinks:before-cache', clearCalendar);

          //events: '/events.json', 以下に追加
          $('#calendar').fullCalendar({
              events: '/worships/calendar.json',
              //カレンダー上部を年月で表示させる
              
              titleFormat: 'YYYY年 M月',
              //曜日を日本語表示
              dayNamesShort: ['日', '月', '火', '水', '木', '金', '土'],
              //ボタンのレイアウト
              header: {
                  left: '',
                  center: 'title',
                  right: 'today prev,next'
              },
              //終了時刻がないイベントの表示間隔
              defaultTimedEventDuration: '03:00:00',
              buttonText: {
                  prev: '前',
                  next: '次',
                  prevYear: '前年',
                  nextYear: '翌年',
                  today: '今日',
                  month: '月',
                  week: '週',
                  day: '日'
              },
              // Drag & Drop & Resize
              editable: true,
              //イベントの時間表示を２４時間に
              timeFormat: "HH:mm",
              //イベントの色を変える
              eventColor: '#87cefa',
              //イベントの文字色を変える
              eventTextColor: '#000000',
              eventRender: function(event, element) {
                  element.css("font-size", "0.8em");
                  element.css("padding", "5px");
              }
          });
      }
  });
});
```

こう

で、`View` に `calendar` っていう `id` があれば
データは入ってないけどカレンダーが表示されるはず

しかしされない
むむむ

___


```
//= require jquery/dist/jquery.js
```

を消して

```
//= require jquery
```

を追記した。
すると表示される。

どうやら `fullcalendar-rails` は `rails-jquery` じゃないとだめみたい
`yarn` のじゃだめみたい

すると無事カレンダーは表示された

___


つぎは `rails` との連携
流れとしては

フロント側からバックエンドに `API` みたいなのを叩いて
`json` 形式のファイルを要求

`json` の情報を元にカレンダーを表示する。

という流れ

ちなみにこの `json` をかえすバックエンドのファイルは `jbuilder `
`scaffold` でいつもできるやつ

いつもスルーしてたけどようやく日の目をみた

___


まずは

```:js
  //events: '/events.json', 以下に追加
          $('#calendar').fullCalendar({
              events: '/worships/calendar.json',
              //カレンダー上部を年月で表示させる
              
              titleFormat: 'YYYY年 M月',
              //曜日を日本語表示
              dayNamesShort: ['日', '月', '火', '水', '木', '金', '土'],
              //ボタンのレイアウト
```

上のコードの `events: '/worships/calendar.json',` の部分で `json` をかえすファイルを指定

このファイルは

```:calendar.json.jbuilder

json.array!(@worships) do |event|
  json.extract! event, :id
  json.title event.id
  json.start event.worship_day
  json.url worship_url(event, format: :html)
end

```

こんなかんじ。
これを `JS` 側から叩くと `json` 形式でデータがかえってくる

でかえってきた情報を元にカレンダーを表示する

上のコードだと

`@worshils` に表示したDBのインスタンス情報があって
`json.title` の情報がカレンダーのラベルに表示される情報

`json.start` っていう内容でカレンダーのどこに表示されるのかが決まる

`json.url` は表示された情報をクリックしたら飛ぶ `URL`


今回の場合だと

[![Image from Gyazo](https://i.gyazo.com/f34b60467dee78a17a0e98985346a24c.png)](https://gyazo.com/f34b60467dee78a17a0e98985346a24c)

こうなる


___

次はラベルの部分を神社名にする

参拝と神社は違うテーブルで、アソシエーションが組んであった

なので

```
json.array!(@worships) do |event|
  json.extract! event, :id
  json.title event.shinto.name
  json.start event.worship_day
  json.url worship_url(event, format: :html)
end

```

上の `event.shinto.name` で情報は取り出せるはずだった。

しかし

[![Image from Gyazo](https://i.gyazo.com/981abc79c12c02e6588f56926041cc36.png)](https://gyazo.com/981abc79c12c02e6588f56926041cc36)

こんなかんじで、`json`ファイルが要求される度に大量のクエリが流れて
表示されるということになってしまった。

表示はされるけどあまりに遅い

どうやら `@worships` の中のプロパティなら問題ないのに外部キーを指定すると
すべての情報を `build` する仕様みたい

___

`jbuilder` のファイルを以下のようにした

```
json.array!(@worships) do |event|
  json.extract! event, :id
  json.title event.shinto.name if params[:start] < event.worship_day.to_s && event.worship_day.to_s < params[:end]
  json.start event.worship_day
  json.url worship_url(event, format: :html)
end

```
`params[:start]` には表示している付きの開始日が、`params[:end]` には終了日が入るので
後置 `if` で条件分岐して、必要な情報だけ引っ張るようにする

すると無事神社名がラベルに表示される


長かった。

カレンダーに表示させているラベル名と詳細のテーブルが違ったらこの記事が参考になるかもです。