[Rails] DBの値を反映するレーダーチャートの実装（Chart.js 3.5.1, gon）

#はじめに
オプションの設定で意図しない動作に苦しめられた。

何に苦しめられたかを結論から話すと、最新版の3.x.x系をインストールしているのに2.x.x系のドキュメント、記事を参考に進めてしまっていたこと。

yarn経由の導入ではバージョンを指定しないと3.x.x系の最新版が手に入ってしまう。

安定板は2.x.x系なので、公式ドキュメントも多くの記事も2.x.x系で解説されおり、そちらを参考にしていたため意図しない動作に見舞われてしまった。

[公式ドキュメント](https://www.chartjs.org/docs/latest/getting-started/v3-migration.html)の[入門]→[3.x移行ガイド]を参考に実装。

結果としてバージョン3.5.1で解決できたので、その備忘録としてレーダーチャートの実装を記事にまとめる。

バージョンを意識する大切さがよくわかりました。

##環境
Rails 6.1.4
chart.js 3.5.1
gon 6.4.0


#スクショ
![Image 2021-10-10 at 12.07.50 PM](https://p8.f1.n0.cdn.getcloudapp.com/items/d5u6B26O/43e1a803-4eb2-4605-8ea1-27edddd8f9bb.jpg?v=7a3abb751ed2b6b84dba8530e75dc580)

導入から完成図まで、これとそのまんま同じになる。

##chart.jsの導入
```terminal
yarn add chart.js
```
yarn経由で`Chart.js`をインストール。
ここでバージョンを指定しないと最新版がインストールされる事になる。
安定板は

```app/javascript/packs/application.js
import 'chart.js/dist/chart';
```
ひとまず導入は完了。


##動作確認
```termminal
rails g controller graphs index
```
動作確認を行うためにトップページを設定する。

```config/routes.rb
Rails.application.routes.draw do
  root to: 'graphs#index'
end
```
ルーティングを設定。

```app/views/graphs/index.html.erb
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            y: {
                beginAtZero: true
            }
        }
    }
});
</script>
```
公式サイトにあるサンプルを貼りつけてスクショと同じようにグラフが表示されていればOK。


#本題
###javascriptファイルを作成
```terminal
touch app/javascript/packs/graph.js
```
空のjsファイルを作成。
ここにサンプルで言うところの`<script>`、つまりグラフの部分を書いていく。

```app/javascript/packs/graph.js
document.addEventListener('turbolinks:load', () => {
  // チャートのデータ
  const radarLabel = ["項目１", "項目２", "項目３", "項目４", "項目５", "項目６"];
  const radarData = [1, 2, 3, 4, 5, 0];

　　　　
  const radarChartData = {
    labels: radarLabel,
    datasets: [
      {
        label: 'タイトル',
        data: radarData,
        backgroundColor: 'rgba(255, 99, 132, 0.2)',
        borderColor: 'rgba(255, 99, 132, 1)',
        borderWidth: 1,
        spanGaps: true,
      },
    ],
  };

  const radarChartOption = {
    scales: {
      r: {
        min: 0,
        max: 5,
        ticks: {
          stepSize: 1,
          callback: function (value, index, values) {
            if (value == 0) {
              return 'レベル０';
            } else if (value == 1) {
              return 'レベル１';
            } else if (value == 2) {
              return 'レベル２';
            } else if (value == 3) {
              return 'レベル３';
            } else if (value == 4) {
              return 'レベル４';
            } else if (value == 5) {
              return 'レベル５';
            }
          },
        },
      },
    },
  };

　　　　//チャートを表示
  const radarChartContext = document.getElementById('radar-chart').getContext('2d');
  new Chart(radarChartContext, {
    type: 'radar',
    data: radarChartData,
    options: radarChartOption,
  });
});
```
`type`には、何のチャートを使うかを指定。今回はレーダーチャートの実装が目的なので`radar`と記述。
それ以外のチャートタイプについては[公式ドキュメント](https://www.chartjs.org/docs/latest/charts/radar.html)を参照。

その他の記述の解説

####data
名称|説明
-|-
labels:|データの項目
datasets:|データのカスタマイズを指定
label:|タイトル
backgroundColor:|背景の色
borderColor:|線の色
borderWidth:|線の太さ
spanGaps:|trueならデータのない点、またはnullの点との間に線を描画を許可。

####options
名称|説明
-|-
scales:|軸の設定
r:|指定する軸
min:|軸の最小値
max:|軸の最大値
ticks:|目盛りの設定
stepSize:|目盛り幅の固定サイズ
callback:|データラベルをポイントラベルに変換する。

2.x.x系から3.x.x系の変更では、`ticks`の中にmin,maxを扱わないなど仕様の変更があるため、他記事で2.x.x系を参考にしている時は注意が必要。

##graph.jsファイルの読み込みを有効化
```app/javascript/packs/application.js
require('./graph')
```
これがないと読み込まれないので忘れず記述する。


##表示したい場所にcanvasを記述
```app/views/graphs/index
  <canvas id="radar-chart" width="400" height="400"></canvas>
```
サンプルで貼り付けた`<script>`の部分はjsファイルに移動したので不要。
`<canvas>`を残して`.getElementById('radar-chart')`と同じidを設定する。

名称|説明
-|-
<canvas>|図形を描画
getContext()|グラフィックを描画するためのメソッドやプロパティを持つオブジェクトを返す
2d|2Dグラフィックを描画するためのメソッドやプロパティを持つオブジェクトを返す。

[canvasのgetContext("2d")って何](https://qiita.com/manten120/items/86c087b937708697acec)


![Image 2021-10-11 at 10.25.03 AM](https://p8.f1.n0.cdn.getcloudapp.com/items/p9uNpmr4/519b23a0-5596-450b-83d6-93e3e9f8b2d6.jpg?v=41b012519daafb470f0e2b085b8628de)


#DBから値を取得する方法

`gon`というGemを使用。
このgonはRailsで定義した変数をJavaScriptでも使えるようにするRubyのライブラリ。

DBの値をコントローラからJSファイルに送る工程を辿らせる。

##gonの導入
```gemfile.
gem "gon"
```
忘れずに`bundle install`でGemをインストール。

##コントローラからJSファイルへデータを渡す
```
<%= Gon::Base.render_data %>
```
まずは`gon`を使用するビューファイルに上記のコードを記述。
`<canvas>`の上に配置する。

```app/controllers/graphs_controller.rb
def index
 gon.chart_label = ["項目１", "項目２", "項目３", "項目４", "項目５", "項目６"];
 gon.chart_data = [1, 2, 3, 4, 5, 0];
end
```
`gon.`をつけた変数名を定義。この変数がjacascriptにデータを渡す役割を持つ。


```app/javascript/packs/graph.js
  // チャートのデータ
  const radarLabel = gon.chart_label;
  const radarData = gon.chart_data;
```
直前に定義した変数を`radarLabel`と`radarData`に書き換える。
これでアクションからjsファイルに値を渡す流れができた。

##DBの値を取得
```terminal
rails g model Graph label:string data:integer
```
graphモデルを作成。
忘れず`rails db:migrate`すること。

わかりやすいように`label`と`date`とした。


```app/controllers/graphs_controller.rb
def index
 gon.chart_label = Graph.pluck(:label);
 gon.chart_data = Graph.pluck(:data);
end
```
`pluck()`は引数で指定したカラムの値を配列で返すメソッド。
この記述によってGraphモデルから値を配列として受け取る準備ができた。

##初期データの作成
```db:seeds.rb
list = [
  { label: "項目１", data: 1 },
  { label: "項目２", data: 2 },
  { label: "項目３", data: 3 },
  { label: "項目４", data: 4 },
  { label: "項目５", data: 5 },
  { label: "項目０", data: 0 }
]

Graph.create!(list)
```
`rails db:seed`で初期データを投稿。
サンプルと同じように表示されていれば完了。