【Ruby on Rails】Chartkickでカラム別集計の円グラフを作成

##はじめに
railsでグラフを挿入したかったのでchartkickを使用しました。
導入自体も容易なので、集計結果の円グラフ化の方法を記載します。

参考にしたページ
-[chartkick公式ドキュメント](https://chartkick.com/)
-[Railsでシンプルなグラフを扱うならchart-js-rails よりchartkickを使うべし](https://qiita.com/Y_uuu/items/0d57748954c7cdb9bbcb)
-[爆速で円グラフを実装する[5分]](https://qiita.com/Y_uuu/items/0d57748954c7cdb9bbcb)

##環境
ruby 2.5.1
Rails 5.2.4.3

##前提と目標
ユーザの意見をまとめた**votesテーブル**の**opinionカラム(integer)**から円グラフを作成する。
opinionカラムの値が1の場合は賛成、0の場合は反対で集計しますが、他の値やNULL値が混ざっている状態で作成します。

**votesテーブル**

|id|opinion|
|:-----------------|------------------:|
|1|1| 
|2|1| 
|3|0| 
|4|1| 
|5|0| 
|6|2| 
|7|NULL| 
|8|3| 
|9|NULL| 
|10|0| 

**完成図**

![pie_A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635727/25142c74-2415-ba11-d322-e3b8166891a6.png)
※実機では円グラフの各要素にマウスカーソルを当てると要素数が表示されます。

##Chartkickの導入
参考ページに記載されていますが改めて記載します。

```ruby:Gemfile
gem "chartkick"   #追記する
```
```ruby:Gemfile
$ bundle install
```
```ruby:app/javascript/packs/application.js
//= require chartkick
//= require Chart.bundle  #２行追記する
```

##viewページへの反映
表示させるページはどこでもいいですが今回はpostsコントローラーのindex.html.erbにグラフを表示させたいと思います。

```html.erb:app/views/posts/index.html.erb
<%= pie_chart Vote.group(:opinion).count%>
```
![chart (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635727/cbd99327-f00b-7aaa-27bf-1d0032b00133.png)

これだけでは何を表しているのかよくわからないグラフになっています。。

そこでコントローラーファイルに変数とグラフ用のメソッドを定義します。

```ruby:app/controllers/posts_controller.rb
  def index
    @opinion = Vote.pluck(:opinion)
    @aggregate = aggregateOpinion(@opinion)
    @sum = sumOpinion(@opinion)
  end

  def aggregateOpinion(array)
    result = [["賛成",0],["反対",0],["どちらでもない",0],["無回答",0]]
    array.each do |i|
      if i == 1
        result[0][1] += 1
      elsif i == 0
        result[1][1] += 1
      elsif i == nil
        result[3][1] += 1
      else 
        result[2][1] += 1
      end
    end
    return result
  end

  def sumOpinion(array)
    result = [["総投票数",0],["有効投票数",0],["無効投票数",0]]
    array.each do |i|
      if i == nil
        result[2][1] += 1
      else 
        result[1][1] += 1
      end
    end
    result[0][1] = array.length 
    return result
  end
```
##解説
pluckメソッドで対象のカラムだけを配列で取得しています。
その後、aggregateOpinionメソッドで円グラフ用のデータに整形しています。

result配列のインデックスがそのまま円グラフの表示順になるのでパラメータが
NULL値のものを最後にしてその次に所謂"その他"(今回の場合は[どちらでもない]という名前)が来るようにしています。

sumOpinionメソッドは直接グラフには関係ありませんが総投票数の情報をグラフに載せることが難しいので別途作成しています。


以上の内容を踏まえ、改めてビューページに反映させたいと思います。

```html.erb:app/views/posts/index.html.erb
<%= pie_chart @aggregate, width: "500px"%>
```
![chart (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635727/436baabe-1208-4431-9352-6b41e69ddadf.png)

これでも問題ないですが最後にレイアウトとsumOpinionメソッドで取得した内容をtable要素で表示させて完成です。

```html.erb:app/views/posts/index.html.erb
<%= pie_chart @aggregate,colors: ["#3333cc","#cc3333","#339966","333"], donut: true , width: "500px"%>
<table border="1" width="500">
  <tr>
    <th>総投票数</th>
    <th>有効投票数</th>
    <th>無効投票数</th>
  </tr>
    <tr>
    <th><%=@sum[0][1]%></th>
    <th><%=@sum[1][1]%></th>
    <th><%=@sum[2][1]%></th>
  </tr>
</table> 
```

![pie_A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635727/5da7ea91-8699-69f2-27a7-43a4c4593a5a.png)

##終わりに
いかがでしたでしょうか。もう少しメソッドの部分に応用を効かせられたなぁと自分でも思いますね。。
もちろんchartkickが対応しているのは円グラフだけではないので是非調べてみてください。
見て頂いてありがとうございました!