[Rails] chart.jsでRailsアプリに投稿数推移グラフを描画する [chart.js]

# はじめに
　このたび、Ruby on Railsの学習を始めました。まだまだ初学者ですが、日々の学びや気づき、エラーとの闘いをここに記録していきたいと思います。ご要望、ご指摘もお待ちしております！


# 記事の概要
　アプリで取り扱われるデータを可視化できればと思い、chart.jsを使ってRailsアプリにグラフを描いてみます。
　1. chart.jsの導入手順
　2. 記事投稿数の推移グラフを描いてみる

# chart.jsとは？
　JavaScriptで実装されたグラフをRailsアプリに組込むことができるライブラリです。
　公式
　https://www.chartjs.org/docs/latest/

# 1. chart.jsの導入手順

　Gemfileに記述する。

```ruby:Gemfile
gem 'chart-js-rails', '~> 0.1.4'
```
　そしてターミナルでbundle installを実行する。

```
% bundle install
```
　package.jsonに以下の通り追記。

```ruby:package.json
{
  # 省略
  "dependencies": {
    #省略
    "chart.js": "^2.7.1" # ←ここに追記
  }
}
```
　そしてターミナルでyarn installを実行。

```
% yarn install
```
# 2. 記事投稿数推移グラフを描いてみる

　ここでは、とあるArticleモデルの投稿数推移について、Articlesコントローラーでデータを加工してarticles#indexにグラフ描画することをゴールとします。
　横軸が日付、縦軸が投稿数です。なお、日時データを扱う"groupdate" gemは導入済みとして進めます。

　まず、グラフ描画の基本構成は下記のようになります。[公式ページ](https://www.chartjs.org/docs/latest/)のサンプル参照。

```app/views/articles/index.html.erb
<canvas id="myChart" width="200" height="100"> </canvas>

<script> 
    var ctx = document.getElementById("myChart").getContext('2d');
    var myChart = new Chart(ctx, {
        type: 'bar',                      # 'bar'でグラフタイプを縦棒グラフに指定　
        data: {
            labels: <%= @chartlabels %>,  # 横軸にとるデータ(今回は投稿日付)を埋め込む
            datasets: [{
                label: "投稿数",
                data: <%= @chartdatas %>, # 縦軸にとるデータ(今回は投稿数)を埋め込む
                backgroundColor: 'rgba(255, 80, 120, 1.0)',
                borderColor: 'rgba(255, 80, 120, 1.0)',
                fill: false
            }]
        },
    });
</script>
```
　グラフに渡すデータをarticles_controllerで用意しましょう。インスタンス変数を定義します。

```ruby:app/controllers/articles_controller
class ArticlesController < ApplicationController
  def index
    @articles = Article.all
     
    @article_by_day = @articles.group_by_day(:created_at).size
    # groupdateのgroup_by_dayメソッドで投稿日(created_at)に基づくグルーピングして個数計上。 
    # => {Wed, 05 May 2021=>23, Thu, 06 May 2021=>20, Fri, 07 May 2021=>3, Sat, 08 May 2021=>0, Sun, 09 May 2021=>12, Mon, 10 May 2021=>2}
    
    @chartlabels = @article_by_day.map(&:first).to_json.html_safe
    # 投稿日付の配列を格納。文字列を含んでいると正しく表示されないので.to_json.html_safeでjsonに変換。
    # => "[\"2021-05-05\",\"2021-05-06\",\"2021-05-07\",\"2021-05-08\",\"2021-05-09\",\"2021-05-10\"]"
    
    @chartdatas = @article_by_day.map(&:second)
    # 日別投稿数の配列を格納。
    # => [23, 20, 3, 0, 12, 2]
  end
end
```
　Railsアプリを起動し/indexへアクセスすると縦棒グラフが描画されている。
![9b48f26e7b6e328f9f4e7909036baf80.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430273/d11d7c2a-e7b1-e35d-c546-86baf4fa0805.png)

　次に、累計投稿数を折れ線グラフにして、先ほどのグラフに重ねてみます。

```app/views/articles/index.html.erb
<canvas id="myChart" width="200" height="100"> </canvas>

<script> 
    var ctx = document.getElementById("myChart").getContext('2d');
    var myChart = new Chart(ctx, {
        type: 'bar',                     　
        data: {
            labels: <%= @chartlabels %>,  
            datasets: [{
                label: "日別投稿数",
                data: <%= @chartdatas %>, 
                backgroundColor: 'rgba(255, 80, 120, 1.0)',
                borderColor: 'rgba(255, 80, 120, 1.0)',
                fill: false
            },{ //ここから追記
                label: "累積投稿数",
                data: <%= @cumulative %>, // 縦軸にとる累積投稿数データを埋め込む
                backgroundColor: 'rgba(255, 80, 120, 0.2)',
                borderColor: 'rgba(255, 80, 120, 1.0)',
                type: 'line', // 'line'でグラフタイプを折線グラフに指定
            }]
        },
    });
</script>
```
　累積投稿数データを配列にして、インスタンス変数として用意します。

```ruby:app/controllers/articles_controller
class ArticlesController < ApplicationController
  def index
    @articles = Article.all
     
    @article_by_day = @articles.group_by_day(:created_at).size
    
    @chartlabels = @article_by_day.map(&:first).to_json.html_safe
      
    @chartdatas = @article_by_day.map(&:second)

    # ここから追記
    @cumulative = []
    sum=0
    @chartdatas.each do |a|
      sum = sum + a
      @cumulative<<sum
    end
  end
end
```
　アプリを起動し/indexへアクセスすると、線グラフも表示されました。

![e3ab7a129fe8fecaf3509774075090a5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430273/d699cf4e-44f0-763f-7333-7819e3701e7c.png)

# まとめ
　chart.jsを活用し、記事投稿数推移グラフを縦棒＋折れ線グラフで表現できました。データベースから加工したデータをグラフで表現することができるので、アプリの管理者機能、可視化など幅広く活用できそうです。カスタマイズも柔軟にできそうなので、今後も記事で取扱いたいと思います。
　Rubyでのデータ加工（もっと簡潔にできそう）とJavaScript記述の良いトレーニングにもなりました。