前提・実現したいこと
Ruby on Railsで残業時間を管理するアプリを制作しています。
アプリにおいては、月毎の合計残業時間を、個人、及びグループ毎に集計しグラフにしたいと考えています。
該当のソースコード
schema.rb(本件に不要な属性を省略)
rb
1 create_table "overtimes", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 2 t.date "date", null: false 3 t.bigint "user_id", null: false 4 t.integer "work_time_minute", null: false 5 t.index ["user_id", "date"], name: "index_overtimes_on_user_id_and_date", unique: true 6 t.index ["user_id"], name: "index_overtimes_on_user_id" 7 end 8 9 create_table "users", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| 10 t.string "name", null: false 11 t.string "group", null: false 12 "index_users_on_reset_password_token", unique: true 13 end 14 15 add_foreign_key "overtimes", "users"
overtime.rb
rb
1class Overtime < ApplicationRecord 2 belongs_to :user 3 4 # 月毎の合計残業時間を個人毎に集計するクラスメソッド 5 def self.monthly_chart_data(userid) 6 # {[2019, 4]=>○○○○, [2019, 5]=>○○○○, …} を生成 7 year_and_month_minute_data = Overtime.where(user_id: userid).group("extract(year from date)").group("extract(month from date)").sum(:work_time_minute) 8 # {["2019年4月"=>○○○○, "2019年4月"=>○○○○, …} に成形 9 monthly_hour_data = {} 10 year_and_month_minute_data.each do |key, value| 11 monthly_hour_data["#{key[0].floor}年#{key[1].floor}月"] = (value.to_f / 60).floor(1) 12 end 13 monthly_hour_data 14 end 15 16 17 18 # 月毎の合計残業時間をグループ毎に集計するクラスメソッド) 19 def self.group_monthly_chart_data 20 # {"A": {[2019, 4]=>○○○○, [2019, 5]=>○○○○, …}, "B": … } のようにまとめたいのですが... 21 group_year_and_month_minute_data = Overtime.joins(:user).select("overtimes*, users*").group(:group).group("extract(year from date)").group("extract(month from date)").sum(:work_time_minute) 22 end 23end
発生している問題
月毎の合計残業時間をまとめるクラスメソッドを、個人毎の場合は上記の通り作成できました。
一方グループ毎の場合は、上記のコードでは、以下のエラーメッセージが出ます。
pry(main)> Overtime.joins(:user).select("overtimes*, users*").group(:group).group("extract(year from date)").group("extract(month from date)").sum(:work_time_minute) (2.4ms) SELECT SUM(`overtimes`.`work_time_minute`) AS sum_work_time_minute, `group` AS group, extract(year from date) AS extract_year_from_date, extract(month from date) AS extract_month_from_date FROM `overtimes` INNER JOIN `users` ON `users`.`id` = `overtimes`.`user_id` GROUP BY `group`, extract(year from date), extract(month from date) ActiveRecord::StatementInvalid: Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group, extract(year from date) AS extract_year_from_date, extract(month from dat' at line 1: SELECT SUM(`overtimes`.`work_time_minute`) AS sum_work_time_minute, `group` AS group, extract(year from date) AS extract_year_from_date, extract(month from date) AS extract_month_from_date FROM `overtimes` INNER JOIN `users` ON `users`.`id` = `overtimes`.`user_id` GROUP BY `group`, extract(year from date), extract(month from date)
試した事
Overtimeのクラスメソッドとして記述した結果、上記のようにエラーが出たため、Userのクラスメソッドとして記述した場合はどうなのかを試してみました。
すると、以下のように望んでいる形に近しい結果が得られました。
pry(main)> User.joins(:overtimes).select("overtimes*, users*").group(:group).group("extract(year from date)").group("extract(month from date)").sum(:work_time_minute) (4.0ms) SELECT SUM(work_time_minute) AS sum_work_time_minute, `users`.`group` AS users_group, extract(year from date) AS extract_year_from_date, extract(month from date) AS extract_month_from_date FROM `users` INNER JOIN `overtimes` ON `overtimes`.`user_id` = `users`.`id` GROUP BY `users`.`group`, extract(year from date), extract(month from date) => {["A", 2019, 4]=>1828, ["A", 2019, 5]=>6418, ["A", 2019, 6]=>6247, ["A", 2019, 7]=>4820, ["A", 2019, 8]=>4033, ["A", 2019, 9]=>6835, ["A", 2019, 10]=>6717, ["A", 2019, 11]=>5469, ["A", 2019, 12]=>4882, ["A", 2020, 1]=>4365, ["A", 2020, 2]=>6504, ["A", 2020, 3]=>5693, ["A", 2020, 4]=>2593, ["B", 2019, 4]=>1414, ["B", 2019, 5]=>4339, ["B", 2019, 6]=>5215, ["B", 2019, 7]=>3992, ...
データの性格上、UserではなくOvertimeのクラスメソッドで上記の結果を得たいのですが、どのように記述すれば同様の結果が得られるかわからないため、お手数ですがご教示いただきたいです。
参考にした情報
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。