StatisticsControllerの一部の処理をサービスクラスに移行する

アプリ制作

  • 週間・月間のグラフ描画機能

    • クエリパラメータで、column, date_begin, date_end, periodを指定して、それを元にグラフを描画できるようになった。
    • date_beginまたはdate_endとperiodを受け取って、ex_beginまたはnext_endを返すメソッドをstatistic_controller.rb のprivateに定義した。
  • グラフ描画のためのデータ(@report)を生成するためのサービスクラスを定義する

    • StatisticControllerが肥大化して分かりにくいため。
  • サービスクラスはapp/lib配下に置く必要がある。

  • app/lib/report/generate_report.rbの作成

結果

#app/controllers/statistics_controller.rb
class StatisticsController < ApplicationController
  before_action :require_user_logged_in, :set_current_user

  def report
    set_params(statistics_params)
    @chart  = Report::GenerateReport.new(current_user, @column, @period, @date_begin, @date_end).call
    @ex_begin = to_ex_or_next_period(@date_begin, @period)
    @next_end = to_ex_or_next_period(@date_end,@period)
  end

private

  def set_params(params)
    @column = params[:column].nil? ? :activity : params[:column].to_sym
    @period = params[:period].nil? ? :weeks : params[:period].to_sym
    @date_begin = params[:date_begin].nil? ? Date.today.begininng_of_week : parse_date(params[:date_begin])
    @date_end = params[:date_end].nil? ? Date.today.end_of_week : parse_date(params[:date_end])
  end

  def statistics_params
    params.permit(:column, :date_begin, :date_end, :period).to_h
  end

  def to_ex_or_next_period(date, period)
    case period
    when :months
      if date == date.beginning_of_month
        date.prev_month.beginning_of_month
      else date == date.end_of_month
        date.next_month.end_of_month
      end
    when :weeks
      if date.cwday == 1
        date.ago(7.days)
      else date.cwday == 7
        date.since(7.days)
      end
    else
      raise "pass valid argument"
    end
  end
end
#app/lib/report/generate_report.rb
module Report
  class GenerateReport
      def initialize(user, column, period, date_begin, date_end)
        @user = user
        @column = column
        @period = period
        @date_begin = date_begin
        @date_end = date_end
      end

      def call
        chart_data(@user, @column, @date_begin, @date_end, @period)
      end

      private

      def chart_data(user, column, date_begin, date_end, period)
        x_axis_data = (date_begin..date_end).to_a
        y_axis_data = data_generator(user, x_axis_data, column)
        chart_data = { labels: x_axis_data, datasets: y_axis_data}
      end

      def data_generator(user, x_axis_data, column)
        x_axis_data.map do |date|
        user.diaries.where(diary_date: date).pluck(column)[0]
      end
    end
  end
end

プロを目指す人のためのRuby入門

  • モジュールについてもっと詳しく