suzy1031 / everyday-study-app

0 stars 0 forks source link

study.total(最新のtotalのデータ)を取得する #9

Closed suzy1031 closed 3 years ago

suzy1031 commented 3 years ago
rails側
created_atが最新のレコード1件をorder()とlimit(1)を使って変数に格納
jsonでrenderする

vue側
axiosでgetしたら.thenの処理の中で配列0番目を取得する
右辺のresponse.dataにデータがたくさん入っている
→console.log(response.data)でオブジェクトの中身を確認
response.dota[0]とする事で0番目の配列を取得し、左辺のthis.latestTotalに格納する
<template>内の表示させるタグ内にて{{ latestTotal.total }}とする事で配列latestTotal[0].totalが取得できる

課題

考え方

実装方針

今週(日〜土)のデータのみ取得→rails(model)内→fat controllerを避ける
→contollerではmodelから受け取ったデータを返すだけにする

# 今週日曜日(日曜始まり)を取得するメソッド
Date.today.beginning_of_week - 1
=> Mon, 15 Nov 2020

# 今週土曜日を取得するメソッド
Date.today.end_of_week.end_of_day - 1.day
=> Sat, 21 Nov 2020 23:59:59 UTC +00:00

# 今週日曜日〜今週土曜日まで取得するメソッド
Study.where(created_at: Date.today.beginning_of_week - 1..Date.today.end_of_week.end_of_day - 1.day).sum(:time)

参考 railsのActiveRecordで最新のレコード1件取得する

suzy1031 commented 3 years ago

これだと、vue.js側の日付処理と曜日が合わず不整合があった vue.js →日曜日起算(日曜日になると今週が開始する) rails →end_of_weekメソッドは月曜日起算で今週末の曜日を取得するので日曜日を取得する

修正後

# study.rb
@this_day = Date.today
self.where(created_at: @this_day - (@this_day.wday)..@this_day - (@this_day.wday - 1)).sum(:time)
suzy1031 commented 3 years ago

これだと、今日が11/23だと、11/22~11/23の間のデータしか取得できていない

# study.rb
+Date.today.beginning_of_week(:sunday)
+Date.today.end_of_week(:sunday)

@this_day = Date.today # 今日の日付
+@this_sunday = @this_day.beginning_of_week(:sunday) # 日曜日
+@this_saturday = @this_day.end_of_week(:sunday) # 土曜日
-self.where(created_at: @this_day - (@this_day.wday)..@this_day - (@this_day.wday - 1)).sum(:time)
+self.where(created_at: Date.today.beginning_of_week(:sunday)..Date.today.end_of_week(:sunday)).sum(:time)

modelメソッドの書き方

# study.rb
def self.変数名
self.メソッド
end

# studies_controller.rb
latestTotal = Study.変数名

この場合、self=Study(モデル名)

参考 wdayメソッドで日付を曜日分逆算する biginning_of_weekとend_of_weekに引数を渡して週の始まりと終わりを指定する 今週、月〜日曜日の日付を動的に取得する https://ginpen.com/2015/08/03/one-liner-weekday-js/

suzy1031 commented 3 years ago

参考 beginning_of_week end_of_week end_of_week(Rails active_support) .sum(:カラム名) study-timer(自分のプロジェクト)

suzy1031 commented 3 years ago

totalをlatestTotal + timeを計算した値をformで送りたい vue.js v-modelは初期値を送れない →計算結果をvauleにセットしてフォームで送るjQuery的な書き方はできなさそう v-modelとvalueは一緒に書けない →:value=“”と@input=“”を省略して書けるのがv-modelの為

suzy1031 commented 3 years ago

latestTotal(studiesに変数名を変更)に格納されているjsonデータは1週間のtimeの合計値しか入っていない modelで.sum(:time)するとjsonデータが日〜土の合計されたtimeしか渡されてない ※railsの1アクション内でrenderできるjsonは1つだけ。

@data1 = ~
@data2 = ~

みたくjsonではインスタンス作りまくってフロント(erb)で@data1.hoge``@data2.piyoみたく受け取れない rails study.rb(モデル) .sum(:time)をしないでjsonで配列データを送る

suzy1031 commented 3 years ago

lengthが定義されていないエラー 原因dataのstudiesが配列で用意されていない為? response.data(配列)を受け取る配列の箱を準備

-studies: ‘’
+studies: []

computedプロパティを使ってループ処理を追加する 計算した結果をtemplate内に{{ calculateTotal }}と修正

完成

  1. axiosで配列データを取得する
    # 配列データの一番最後を取得
    this.userTotal = response.data.slice(-1)[0]
    {"id" : "1", "time" : "1", "total" : "3"}
    {"id" : "2", "time" : "2", "total" : "4"}
    {"id" : "3", "time" : "3", "total" : "5"} ← このjsonデータを取得し配列に格納
  2. this.userTotal.totalで最後の配列内のtotalを取得する
  3. axios.post内で計算処理を行う
    # jsonはstring型なので、float型に変換する
    parseFloat(this.userTotal.total)
    # セレクトボックスに入力されたvalueをstring→floatに変換する
    parseFloat(this.study.time)
    # 計算する
    var calcTotalValue = parseFloat(this.userTotal.total) + parseFloat(this.study.time)
  4. v-modelとaxios.postを使ってフォームを送信する
    # this.studyに3の計算結果とセレクトボックスで選択したvalueを格納
    this.study.total = calcTotalValue;
    this.study.time = this.time // これは書かなくてもv-modelディレクティブでバインドされている
    # axios.postの第2引数にdataを渡す
    axios.post('/api/v1/studies', this.study)

DBを確認すると直前の最新レコードのtotal + 入力したthis.timeの合計値がtotalのvalueとしてinsertされている

suzy1031 commented 3 years ago

次の課題 日曜日になると、jsonで受け取るデータは空になるはず calcTotalValueの計算ができないのではないか?

方針

postStudyTimeメソッドの変数calcTotalValue

0 + this.time = 今日の学習時間がstudy.totalに登録されてしまう ↓ this.userTotal = response.data.slice(-1)[0] → 取得するデータは前日データ 例 今日が11/28(金)→取得するデータは11/27(木)→これは11/22~11/29までrails側で取得しているから問題無し 今日が11/30(日)→取得するデータは11/29(土)→これだとrails側で取得データするのは11/30~12/5なので駄目


***上記エラーケースを解消するには***
1. rails側で11/29~12/5のデータを取得できるように修正
2. calcTotalValueはそのまま使える
3. calcThisWeekTotalメソッドを修正→取得したデータ個数 - 11/29のデータを計算し出力
suzy1031 commented 3 years ago

もし土曜日に入力した時間がなかった場合、取得できるデータが無い為、undefinedになる 曜日に関わらず最後に入力されたtotalを取得する必要がある

考え方

# 条件は3つ
今日が日曜 && データ1件件以上
→ Study.where(created_at: @this_sunday..@this_saturday)でデータを取得
今日が日曜日以外
→ Study.where(created_at: @this_sunday..@this_saturday)でデータを取得
それ以外(今日が日曜日 && データが0件)
→ Study.order(created_at: :desc).limit(1)でデータを取得
→ 更にtotalだけ取得にする
study.rb
+now = Time.current
+range = now.all_day
# rails c
@data = Study.where(created_at: range)
 Study Load (1.1ms)  SELECT  `studies`.* FROM `studies` WHERE `studies`.`created_at` BETWEEN '2020-11-29 00:00:00' AND '2020-11-29 23:59:59' LIMIT 11
=> #<ActiveRecord::Relation [#<Study id: 41, time: 0.5, total: 9.0, user_id: nil, created_at: "2020-11-29 02:59:12", updated_at: "2020-11-29 02:59:12">, 
#<Study id: 42, time: 0.5, total: 9.5, user_id: nil, created_at: "2020-11-29 02:59:45", updated_at: "2020-11-29 02:59:45">]>
suzy1031 commented 3 years ago

rails activeRecordメソッド

@this_day = Date.today # 今日の日付
@this_sunday = @this_day.beginning_of_week(:sunday) # 日曜日
@this_saturday = @this_day.end_of_week(:sunday) # 土曜日
self.where(created_at: @this_sunday..@this_saturday)
+@this_day = Time.now
+range = @this_day.all_week(:sunday)
+self.where(created_at: range)
# すっきり書けた
suzy1031 commented 3 years ago

条件変更 rails

考え方

vue.js

suzy1031 commented 3 years ago

27日と1日だけで比較すると、27の方が大きくなっていて想定結果を取得できない 取得データをDate型にする 今週の日曜を取得する(thisWeekDate()と同じ処理) 2つを比較する

vue.js jsonで取得したデータの日付チェック 最後の配列が今週の曜日の場合 → 今まで通り 最後の配列が先週の曜日の場合 → 0を出力

参考 .present?メソッド all_dayメソッド Time.now.all_dayメソッド getTime()メソッド 日付の比較

suzy1031 commented 3 years ago

土曜日になると土曜日のデータを取得できていない

class Study < ApplicationRecord

def self.this_week_total
-@this_day = Date.dotay 
+@this_day = Time.now # 今日の日付
@this_date = @this_day.wday # 今日の曜日取得
@range = @this_day.all_week(:sunday) # 日曜日始まりで今週の日〜土を取得
@data = Study.where(created_at: @range) # 今週の日〜土のデータを取得

# 今週チェック
if (@this_date && @data.present?) # 今週の日〜月または今週のデータが1件以上の場合
self.where(created_at: @range) # 今週の日〜土のデータ取得
else # 今週ではないかつ今週のデータが0件の場合
self.order(created_at: :desc).limit(1) # 最新レコードを1件取得
end
end

end

Time.nowを使って23:59:59までのデータを取得できるように修正