[Ruby on Rails]色の割合を明示する円グラフを実装する


自身が欲しいのと、作ってみたら面白そうという思いの元、現在、自身の服を管理できる「クローゼットアプリ」のようなものを、個人で作成しています。
そこで自身の服の色の割合を、円グラフでわかりやすく表示できれば、いいなと思い今回実装いたしました。

#開発環境
Ruby 2.5.1p57
Rails 5.2.4.4
使用gem
　　・active_hash
　　・chartkick
　　・chartable

#実際に作っていく
今回実際の色のデータをどこに持たせるか非常に悩みましたが、active_hashを使用し、モデルにハッシュ形式で、データを持たせ、そのIDを「colors」というデータベースに保存することにしました。

まずGemfileに下記を記述します。

```ruby:Gemfile
#~省略~
gem 'active_hash'
gem "chartkick"
gem 'chartable'
#~省略~
```

application.jsに下記を記述します。

```javascript:application.js
//= require Chart.bundle
//= require chartkick
```

そしてActive_hashを用いて、実際の色データを持たせたモデルがこちらです。

```ruby:color_data.rb
class ColorData < ActiveHash::Base
  self.data = [
    { id: 1, name: 'ホワイト', backcolor: "#fff" },
    { id: 2, name: 'ブラック', backcolor: "#000" },
    { id: 3, name: 'グレー', backcolor: "#808080" },
    { id: 4, name: 'ブラウン', backcolor: "#660000" },
    { id: 5, name: 'ベージュ', backcolor: "#FFE4C4" },
    { id: 6, name: 'グリーン', backcolor: "#006400" },
    { id: 7, name: 'ブルー', backcolor: "#0000CD" },
    { id: 8, name: 'パープル', backcolor: "#8B008B" },
    { id: 9, name: 'イエロー', backcolor: "#FFFF00" },
    { id: 10, name: 'ピンク', backcolor: "#FF82B2" },
    { id: 11, name: 'レッド', backcolor: "#FF0000" },
    { id: 12, name: 'シルバー', backcolor: "#C0C0C0" },
    { id: 13, name: 'ゴールド', backcolor: "#DAA520" }
  ]
end
```
こんな感じで書きました。「backcolor」というkeyは円グラフのそれぞれの項目に指定した色を渡すためのデータです。

そしてmodel。
コントローラーに、グラフのデータは、ハッシュ形式で渡し、背景色のデータは、配列として渡したかったので、かなり助長で、同じことを繰り返している冗長なコードになっています、、、。ここはもっといいやり方を模索します。

```ruby:color.rb
class Color < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :color_data
  class << self
    #グラフに渡すハッシュデータを形成するメソッド
    def color_data_acquisition_for_graphs
      colors = all
      color_graph_data = {}
      colors.each_with_index do |color, index|
        color_graph_data = { color.color_data.name => 1 } if index.zero?
        #eachでDBから取得したデータを回し、既に、keyとして存在しているかをチェックする
        #もう既に存在していれば割合の基準となるvalueに1を足していく
        if color_graph_data.key?(color.color_data.name)
          color_graph_data[color.color_data.name] += 1
        else
          color_graph_data[color.color_data.name] = 1
        end
      end
      color_graph_data
    end

    def background_color_data_acquisition_for_graphs
      colors = all
      color_graph_data = {}
      background_colors = []
      colors.each_with_index do |color, index|
        if index.zero?
          color_graph_data = { color.color_data.name => 1 }
          #背景色のデータ（backcolorのデータ）を追加していく
          background_colors << color.color_data.backcolor
        end
        if color_graph_data.key?(color.color_data.name)
          color_graph_data[color.color_data.name] += 1
        else
          color_graph_data[color.color_data.name] = 1
          #まだ取り込んでいないkeyが来た時にbackcolorを追加していくために順番が守られる
          background_colors << color.color_data.backcolor
        end
      end
      background_colors
    end
  end
end
```

ここは参考にしないでください笑（いい書き方があればどなたか、、、）

そしてここで作成したデータをコントローラに渡します。

```ruby:closet_controller.rb
class ClosetController < ApplicationController
  def index
    @color_graph_data = Color.color_data_acquisition_for_graphs
    @background_colors = Color.background_color_data_acquisition_for_graphs
  end
end
```

そしてビューにグラフ用の集計データと、グラフに色をつける用のデータを渡します。

あとは表示するだけです。

```ruby:index.html.slim
= pie_chart @color_graph_data, colors: @background_colors
```

これだけで、、、

![スクリーンショット 2020-10-11 14.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624989/b519b9cd-c42e-7037-33d3-b61f095f8fc2.png)

このように表示する事ができます。

ちなみにメニューの項目が要らなければ、config/initializers/以下に「chartkick.rb」というファイルを作成し、オプションを書く事で非表示にすることもできます。

```ruby:chartkick.rb
Chartkick.options = {
  legend: false
}
```

こうすることで、、、

![スクリーンショット 2020-10-11 14.39.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624989/8370eb13-b10c-72bb-d4c2-ea2d1273b9b7.png)

初めは、色によってバックグラウンドに指定する色を条件分岐したりしないといけないのかなと思ったりもしましたが、そもそものActive_hashの時点でそれぞれの背景色の値を持たせることを思いつけたので良かったです。

個人アプリでは史上最多の28個ものテーブルを持つ開発になるので楽しみながら頑張っていきます。