[Ruby] [Ruby on Rails] Create a pie chart that aggregates by column with Chartkick

2 minute read

Introduction

I used chartkick because I wanted to insert a graph with rails. Since the introduction itself is easy, we will describe the method of making the pie chart of the aggregated results.

Referenced page

environment

ruby 2.5.1 Rails 5.2.4.3

Assumptions and goals

Create a pie chart from the opinion column (integer) of the votes table that summarizes user opinions. If the value of the opinion column is 1, it is agreed, and if it is 0, the opposite is counted, but it is created with other values and NULL values mixed.

votes table

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

Completion drawing

pie_A.png

  • On the actual machine, if you move the mouse cursor to each element of the pie chart, the number of elements will be displayed.

Introduction of Chartkick

It is described on the reference page, but it will be described again.

Gemfile


gem "chartkick" # add

Gemfile


$ bundle install

app/javascript/packs/application.js


//= require chartkick
//= require Chart.bundle # add 2 lines

Reflect on view page

You can display the page anywhere, but this time I want to display the graph in index.html.erb of the posts controller.

html.erb:app/views/posts/index.html.erb


<%= pie_chart Vote.group(:opinion).count%>

chart (1).png

It is a graph that I do not know what it represents by itself. ..

So in the controller file define variables and methods for the graph.

app/controllers/posts_controller.rb


  def index
    @opinion = Vote.pluck(:opinion)
    @aggregate = aggregateOpinion(@opinion)
    @sum = sumOpinion(@opinion)
  end

  def aggregateOpinion(array)
    result = [["yes",0],["opposite",0],["neither",0],["no answer",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 = [["total votes",0],["valid votes",0],["invalid votes",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

Comment

Only the target column is acquired as an array with the pluck method. After that, it is formatted into data for pie chart with the aggregateOpinion method.

Since the index of the result array is as it is in the pie chart display order, the parameter The null value is given last, and then the so-called “other” (in this case, the name “Neither”) comes.

The sumOpinion method is not directly related to the graph, but it is difficult to put information on the total number of votes on the graph, so it is created separately.

Based on the above contents, I would like to reflect it again on the view page.

html.erb:app/views/posts/index.html.erb


<%= pie_chart @aggregate, width: "500px"%>

chart (2).png

This is no problem, but at the end it is completed by displaying the layout and the contents acquired by the sumOpinion method with the table element.

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>Total votes</th>
    <th>Valid votes</th>
    <th>Invalid votes</th>
  </tr>
    <tr>
    <th><%[email protected][0][1]%></th>
    <th><%[email protected][1][1]%></th>
    <th><%[email protected][2][1]%></th>
  </tr>
</table>

pie_A.png

At the end

What did you think. I think I could apply the method to the method a little more. .. Of course, chartkick supports not only pie charts, so please check it out. Thank you for watching!