Closed suzy1031 closed 3 years ago
railsのactiveRecordで日別でsumしたデータへ整形してjsonでレスポンスした方が良さそう
# todo 仮データ=>今週のデータのみ取得するメソッドを追加
Study.select(:id, "sum(time) as time", :created_at).group("date(created_at)")
Study Load (0.6ms) SELECT `studies`.`id`, sum(time) as time, `studies`.`created_at` FROM `studies` GROUP BY date(created_at) LIMIT 11
=> #<ActiveRecord::Relation [
#<Study id: 1, time: 1.0, created_at: "2021-01-17 02:01:20">,
#<Study id: 3, time: 4.0, created_at: "2021-01-18 03:00:00">,
#<Study id: 5, time: 3.5, created_at: "2021-01-19 03:00:00">,
#<Study id: 8, time: 0.5, created_at: "2021-01-21 03:00:00">,
#<Study id: 9, time: 0.5, created_at: "2021-01-22 03:00:00">,
#<Study id: 10, time: 1.0, created_at: "2021-01-23 03:00:00">
]>
routes.rbを設定
+get 'histories', controller: :studies, action: :history
studies_controller.rbを設定
-protect_from_forgery except: [:index, :create, :update, :destroy]
+protect_from_forgery except: [:index, :history, :create, :update, :destroy]
+def history
# todo modelメソッドにする. 今週のデータのみ取得する
+histories = current_user.studies.select(:id, "sum(time) as time", :user_id, +:created_at).group("date(created_at)")
+render json: histories
+end
jsonを確認してみる http://localhost:3000/api/v1/histories
[
{"id":1,"time":1.0,"user_id":1,"created_at":"2021-01-17T11:01:20.000+09:00"},
{"id":3,"time":4.0,"user_id":1,"created_at":"2021-01-18T12:00:00.000+09:00"},
{"id":5,"time":3.5,"user_id":1,"created_at":"2021-01-19T12:00:00.000+09:00"},
{"id":8,"time":0.5,"user_id":1,"created_at":"2021-01-21T12:00:00.000+09:00"},
{"id":9,"time":0.5,"user_id":1,"created_at":"2021-01-22T12:00:00.000+09:00"},
{"id":10,"time":1.0,"user_id":1,"created_at":"2021-01-23T12:00:00.000+09:00"}
]
必要なデータが取得できている
History.vue
でapi
からjsonを受け取る
export default {
data() {
+histories: [],
}
}
mounted () {
+this.$http.secured.get('/api/v1/histories')
+.then(response => {
+this.histories = response.data
this.fillData()
+})
}
methods: {
arrayData () {
# todo データが無い曜日は0を配列に追加する
+var getData = this.histories;
const times = getData.map(item => item.time)
return times
}
}
fillData () {
this.loaded = false
+var data = this.arrayData()
this.chartData = {
labels: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
datasets: [
{
barPercentage: 0.8,
backgroundColor: '#0066FF',
+data: data
}
]
}
this.loaded = true
},
jsonで取得したデータをchart.jsに渡してグラフを表示するまで完成 データが無い曜日は配列に0を代入する必要がある
# 現状の結果
[1/17(Sun): 1, 1/18(Mon): 4, 1/19(Tue): 3.5, 1/20(Wen): 0.5, 1/21(Thu): 0.5, 1/22(Fri):, 1]
labels: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']に7つに対して、
配列が6つの為、左詰めにデータがマッピングされてしまっている
その為、土曜日のデータが無くなってしまっている
# 期待する結果
[1/17(Sun): 1, 1/18(Mon): 4, 1/19(The):3.5, 1/20(Wen): 0, 1/21(Thu): 1, 1/22(Fri): 0.5, 1/23(Sat): 1]
データが存在しない1/20(Wen)には0を渡し、日付と正しくマッピングする
chartDataに渡す配列データ処理 考え方
map
を使って比較用の配列
を作成するfilter
を使って2つの配列を比較して比較用の配列
内に存在しない数値を取得splice
を使って任意の場所(index番号目の後ろ)に連想配列を追加したgetDataを作成するmap
を使ってデータが7つ存在する新しい配列を作成するarrayData () {
var getData = this.histories;
+if(getData.length < Const.INT_SEVEN) {
// (A)比較用の配列を作成する
+const arrayDayOfWeek = getData.map(item => item.day_of_week)
=> [0, 1, 2, 4, 5, 6]という配列を作成
// (B)比較対象の配列を用意する
+const arraySeven = [0, 1, 2, 3, 4, 5, 6]
// (A)と(B)を比較して差分を求める
+var resultArray = arraySeven.filter(i => arrayDayOfWeek.indexOf(i) == -1)
=> 返り値はarrayDyOfWeekに存在しない「3」
// 差分として返ってきた結果をindexに当てはめる
+for(var i = 0; i < resultArray.length; i++) {
+getData.splice(resultArray[i], 0, {time: 0})
=> 最終的にはtimeの値が欲しいので他のプロパティは不要
+};
+}
const times = getData.map(item => item.time)
return times
},
chart.js使い方 参考 Vue.jsでChart.jsを使ってグラフを描写する Chart.jsで凡例を削除する chart.js:縦のラインを全部非表示にする chart.js 棒グラフ オプション色々 公式
参考 【vue-chart.js】Invalid propエラーを解決!
datasets.dataに渡す配列データを作成するメソッド
参考 【Javascript】配列(オブジェクト)の操作【map/filter/some/reduce】
全ての集計をjs側でやるのは難しい...