Weeklyグラフで前後の期間へのリンク生成で発生するエラーをデバッグ
アプリ制作
実現したいこと1
リクエストが下の2つのパターン両方でグラフ描画を行えるようにする。前者はコントローラのreportbydateアクション, 後者はreportbyperiodアクションにルーティングされている。
statistics/activity/from/2019-10-07/to/2019-10-13
, statistics/activity/period/prevWeek
課題1
statistics/activity/period/prevWeek
で先週のグラフを表示する。これは2019-10-07/to/2019-10-13
の期間のグラフが表示できている。
(1) 次に前週へのリンクを押し, 2019-09-30 ~ 2019-10-06
の期間のグラフを表示する。しかし、この期間のレコードは存在するのにグラフには該当日付のY軸の値が表示されない。
(2) そのまたさらに前週へのリンクを押すと, 本来は2019-09-23 ~ 2019-09-29
の期間がリクエストされるはずにもかかわらず, 2019-08-01 ~ 2019-09-29
の期間がリクエストされる。
課題1がなぜ起こるのか?・修正すべき点と結果
binding.pryでコントローラの@reportが正しく生成されているか確認をした。
2019-09-30 ~ 2019-10-06
の期間, つまり1週間でリクエストをしているのに、MonthlyReportクラスが呼ばれていた。(期間が1ヶ月単位の時に呼び出すように設計したつもりだった)
リクエストされた期間に対して, コントローラ内でWeeklyReportかMonthlyReportかを条件分岐する部分が意図した通りに機能していない。その部分を修正する必要がある。
コントローラではis_date_weekly?メソッドでtrueならWeeklyReport, falseならMonthlyReportを生成するように分岐させていた。2019-09-30 ~ 2019-10-06
のリクエストに対して, このメソッドでfalseを返してしまい, MonthlyReportが生成されてしまっていた。
def is_date_weekly?(date_begin, date_end) (date_begin..date_end).to_a.length <= 7 ? true : false end
なぜそうなるかというと、メソッドの引数date_begin, date_endがStringクラスのまま代入されていた。Dateオブジェクトに変換するように修正すると, WeeklyReportを生成できた。
さらに発生した懸念点
MonthlyReportクラスではgroup_by_monthで月初の日付をキーにしてグループ化したハッシュを作成している。そのためdate_beginが月初の日付でないと, 該当期間のY軸の値をすべてnilにして配列で返してしまう.
(この,keyが見つからない場合にnilの配列を返す処理は, Diaryレコードがない期間のリクエストの際にエラー発生を防ぐ目的で実装していた。)
def data_generator(user, column, date_begin) records = user.diaries.group_by_month(&:diary_date) if records[date_begin].present? records[date_begin].map do |diary| diary.send(column) end elsif records[date_begin].nil? date_range.length.times.map { |n| nil } else raise "Error" end
グループしたHashのキーが存在しなかった場合, 該当期間のY軸がすべてnilになる可能性がある。group_byメソッドの処理を確認したり、Reportクラスの処理を修正する必要があるなと思った。
実現したいこと2
同じカラムで週間→月間, 月間→週間の遷移をする
どのように実装したか?
- 週間→月間
- WeeklyReportクラスにto_monthlyメソッドを作成
- date_beginの
beginning_of_month
,end_of_month
を取得して, URI文字列を返す
- 月間→週間
- MonthlyReportクラスにto_weeklyメソッドを作成
- date_beginとdate_endの日数の差の2分の1の日付を基準日にし、基準日の週の月曜, 日曜をそれぞれdate_begin, date_endにセット
- URI文字列を返す
Viewで@reportがWeekly, Monthlyどちらのクラスのインスタンかを確かめる
#app/views/statistics/report_by_date.html.erb <% if @report.class.method_defined? :to_monthly %> <%= link_to "月間", "#{@report.to_monthly}" %> <% end %> <% if @report.class.method_defined? :to_weekly %> <%= link_to "週間", "#{@report.to_weekly}" %> <% end %>
実装できた。
ここまでに実装した機能(体調グラフ)
URIの形式
期間は週間、月間の2週類
それぞれの期間について、以下のことができる.
- 前後の期間へのリンクを生成する機能(同カラム内)
- 週間→月間、月間→週間へのリンクを生成する機能(同カラム内)
同期間内で異なるカラムへのリンクを生成する機能
プロを目指す人のためのRuby入門
- 第10章 Procとyieldを理解する(2時間)