

**実現したいこと**

Railsでグループ単位で値を集計（SUM)し、各グループごとの集計結果をControllerで変数として定義したい

※その後、定義した変数について、gem gonを活用してJavaScriptに定義した値を加える予定です。

**イメージ**  
[![画像の説明をここに入力](https://i.stack.imgur.com/yzX5g.png)](https://i.stack.imgur.com/yzX5g.png)

### 環境・条件

・Ruby：2.6.5  
・Rails:5.2.4.3  
・DB：PostgreSQL  
・DB設計 ※詳細は下記コード  
親：Recordテーブル（属性：id,その他）  
子：Practiceテーブル（属性：id,practice_item, practice_time）  
※practice_itemで格納される値は、string型かつ決まった文字列

### 試したこと

**構想**  
★ゴール：chart.jsにRuby変数を組み込んで変数の値をaggrigate_results.html.slimに表示させること

そのために必要となる要素  
★全てのRecordテーブルのレコードから、practice_itemごとに格納されている全てのpractice_timeの値を合計したものをオブジェクトとすること

★そのために必要な実装  
1.全てのrecordを取り出す  
2.全てのrecordが取り出せたら、PracticeテーブルのPractice_itemを分類して棲み分けさせる  
3.棲み分けしたpractice_itemの全てのpractice_timeの値をsumメソッドなどで合計値を計算し、それをまた1つのオブジェクトとする  
4.practice_itemごとの合計値が含まれる集合を、ハッシュか配列で定義する  
5.定義したハッシュか配列をViewで表示できるようJSを修正する

★1.2.3を実施（＝Practiceテーブルにある、practice_item,practice_timeを両方検索して取り出す。その後practice_timeをSUM関数で集計）

[code]

      def aggregate_result
    
      @record = current_user.records.includes(:practices).select("practice_item", "practice_time").group("practice_item").sum(:practice_time)
      logger.info "test #{@record}"
      gon.data = @record
      end
    
[/code]

それでログを確認したところ、下記の通りとなったのですが、その後4.5.をどのようにすれば良いのか？ご教授頂ければ幸いです。

※現時点の内容を画面確認しましたが、エラーにはなっていないものの、表示はされていないです。

[![画像の説明をここに入力](https://i.stack.imgur.com/n2ll7.png)](https://i.stack.imgur.com/n2ll7.png)

もしくは、やり方が違うのでは？と言うものがあれば、遠慮なく仰って頂ければ幸いです。

[code]

    tarted POST "/__better_errors/1d27c32fbb9084fd/variables" for ::1 at 2020-06-20 23:40:45 +0900
    Started GET "/records/3/aggregate_result" for ::1 at 2020-06-20 23:40:46 +0900
    Processing by RecordsController#aggregate_result as HTML
      Parameters: {"id"=>"3"}
      User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 3], ["LIMIT", 1]]
      ↳ /Users/user/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-5.2.4.3/lib/active_record/log_subscriber.rb:98
       (0.6ms)  SELECT SUM(practice_time) AS sum_practice_time, practice_item AS practice_item FROM "records" LEFT OUTER JOIN "practices" ON "practices"."record_id" = "records"."id" WHERE "records"."user_id" = $1 GROUP BY practice_item  [["user_id", "3"]]
      ↳ app/controllers/records_controller.rb:57
    test {"多球練習"=>222, "サーブ練習"=>170, "フットワーク"=>30, "オール"=>22, "台上処理"=>120}
      Rendering records/aggregate_result.html.slim within layouts/application
      Rendered records/_flash_messages.html.slim (2.0ms)
      Rendered records/aggregate_result.html.slim within layouts/application (6.1ms)
      Rendered records/_header.html.slim (3.1ms)
      Rendered records/_footer.html.slim (1.6ms)
    Completed 200 OK in 51ms (Views: 29.4ms | ActiveRecord: 5.2ms)
    
    
[/code]

**コード**

Controller

[code]

    class RecordsController < ApplicationController
    before_action :authenticate_user!
    
      def index
        @q = current_user.records.ransack(params[:q])
        @search_records = @q.result(distinct: true).includes(:practices).page(params[:page]).per(8)
      end
    
      def show
        @record = Record.find(params[:id])
      end
    
      def new
        @record = Record.new
        output = @record.outputs.build
        practice = @record.practices.build
        task = @record.tasks.build
      end
    
      def create
        @record = Record.new(record_params)
        logger.info "###### #{@record.inspect}"
        if @record.save
          flash[:success] = "練習内容の登録が完了しました。"
          redirect_to records_url
        else
          flash[:alert] = "登録に失敗しました。"
          render :new
        end
      end
    
      def edit
        @record = Record.find_by(id: params[:id])
      end
    
      def update
        @record = Record.find_by(id: params[:id])
        if @record.update(record_params)
            flash[:success] = "練習内容の更新が完了しました。"
            redirect_to records_url
          else
            flash[:alert] = "更新に失敗しました。"
            render :edit
          end
      end
    
      def destroy
        record = Record.find_by(id:params[:id])
        record.destroy
    
        redirect_to root_path, notice: "練習記録を削除しました。"
      end
    
      def aggregate_result
      @record = current_user.records.includes(:practices).select("practice_item", "practice_time").group("practice_item").sum(:practice_time)
      logger.info "test #{@record}"
      gon.data = @record
      end
    
      private
    
      def set_user
        @user = current_user || User.new
      end
    
      def record_params
        params.require(:record).permit(:record_id, :training_date, :learning_point, outputs_attributes:[:output_name, :id, :_destroy], practices_attributes:[:practice_item, :practice_time, :id, :_destroy], tasks_attributes:[:task_name, :id, :_destroy]).merge(user_id: current_user.id)
      end
    end
    
[/code]

schema.rb（一部）

[code]

    ActiveRecord::Schema.define(version: 2020_05_25_064157) do
    
      create_table "practices", force: :cascade do |t|
        t.string "practice_item"
        t.integer "practice_time"
        t.bigint "record_id"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
        t.index ["record_id"], name: "index_practices_on_record_id"
      end
    
      create_table "records", force: :cascade do |t|
        t.string "user_id"
        t.text "learning_point"
        t.date "training_date"
        t.datetime "created_at", null: false
        t.datetime "updated_at", null: false
      end
    
[/code]

aggregate_result.html.slim

[code]

    = render 'records/flash_messages'
    h1 レポート
    canvas#myPieChart
    script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.js"
    javascript:
      var ctx = document.getElementById("myPieChart");
      var myPieChart = new Chart(ctx, {
        type: 'pie',
        data: {
          labels: ["サーブ練習", "フットワーク", "3球目攻撃", "台上処理","多球練習","オール"],
          datasets: [{
              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(75, 192, 192, 0.2)',
                'rgba(242,68,172,0.2)'
              ],
              data: gon.data
          }]
        },
        options: {
          title: {
            display: true,
            text: '練習内容の内訳'
          }
        }
      });
    
    = link_to '一覧に戻る', root_path, class: 'btn btn-primary'
    
    
[/code]


CC BY-SA 4.0
2020-06-20T14:52:42.140
67839
2022-12-27T06:01:35.207
2020-06-20T16:17:52.740
3060
39475
question
ruby-on-rails ruby postgresql chart.js
Railsでグループ単位で値を集計（SUM)し、各グループごとの集計結果を表示させたい


chart.jsで表示するデータは配列で渡すようです。  
<https://www.chartjs.org/docs/latest/charts/doughnut.html#data-structure>

`aggregate_result.html.slim`でデータを渡している`gon.data`を配列に変えればグラフが表示されそうです。  
また、SlimでインラインJavascriptを使うのであれば、Gon経由で渡さずに変数展開しちゃえばいいかなと思います。

[code]

    var ctx = document.getElementById("myPieChart");
    var myPieChart = new Chart(ctx, {
      type: "pie",
      data: {
        labels: #{@record.keys},
        datasets: [
          {
            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(75, 192, 192, 0.2)",
              "rgba(242,68,172,0.2)",
            ],
            data: #{@record.values},
          },
        ],
      },
      options: {
        title: {
          display: true,
          text: "練習内容の内訳",
        },
      },
    });
    
[/code]


CC BY-SA 4.0
2020-06-21T00:46:32.480
67851
2020-06-21T00:46:32.480
40752
67839
answer