Skip to content

Instantly share code, notes, and snippets.

@prfraser
Created September 25, 2024 04:09
Show Gist options
  • Save prfraser/409407b3109f0cf858bae1fbcae5aa75 to your computer and use it in GitHub Desktop.
Save prfraser/409407b3109f0cf858bae1fbcae5aa75 to your computer and use it in GitHub Desktop.
def save_report
result = SaveReportService.call(@report_params)
if result.success?
redirect_to workforce_report_path(result.report.report_key, params: { saved_report_id: result.report.id }),
notice: "Report saved successfully"
else
redirect_to workforce_report_path(params[:id]), alert: result.error_message
end
end
private
def set_report_params
@report_params = ReportParamsService.build(params)
end
# typed: strict
# frozen_string_literal: true
class ReportParamsService
extend T::Sig
sig { params(params: ActionController::Parameters).returns(Types::WorkforceReportsController::TReportParams) }
def self.build(params)
new(params).build
end
sig { params(params: ActionController::Parameters).void }
def initialize(params)
@params = params
end
sig { returns(Types::WorkforceReportsController::TReportParams) }
def build
if @params[:saved_report_id].present?
build_from_saved_report
else
build_from_params
end
end
private
sig { returns(Types::WorkforceReportsController::TReportParams) }
def build_from_saved_report
saved_report = SavedReport.find(@params[:saved_report_id])
filters = symbolize_keys(saved_report[:params])
Types::WorkforceReportsController::TReportParams.new(
id: @params[:id].to_s,
page: @params[:page].try(&:to_i) || 1,
per_page: @params[:per_page].try(&:to_i) || 25,
format: @params[:format]&.to_s || "html",
user_id: saved_report[:user_id],
saved_name: saved_report[:name],
saved_description: saved_report[:description] || "",
http_method: saved_report[:http_method],
path: saved_report[:path],
filters: Types::WorkforceReportsController::TFilterParams.new(filters)
)
end
sig { returns(Types::WorkforceReportsController::TReportParams) }
def build_from_params
filters = extract_filters
Types::WorkforceReportsController::TReportParams.new(
id: @params[:id].to_s,
page: @params[:page].try(&:to_i) || 1,
per_page: @params[:per_page].try(&:to_i) || 25,
format: @params[:format]&.to_s || "html",
user_id: @params[:user_id].try(&:to_i),
saved_name: @params[:saved_name].try(&:to_s),
saved_description: @params[:saved_description].try(&:to_s),
http_method: @params[:method]&.to_s || @params[:http_method],
path: @params[:path]&.to_s,
filters: Types::WorkforceReportsController::TFilterParams.new(filters)
)
end
sig { returns(T::Hash[Symbol, T.untyped]) }
def extract_filters
report_filter_types = WorkforceReport::Components::Filter.values.map(&:enum_to_underscore)
filters = @params.select { |key, _| report_filter_types.include?(key) }
filters_hash = filters.to_unsafe_h.symbolize_keys
filters_hash_transformed = filters_hash.transform_values { |v| (v.is_a?(String) && v.empty?) ? nil : v }
valid_filter_params = Types::WorkforceReportsController::TFilterParams.props.keys.map(&:to_sym)
filters_hash_transformed.slice(*valid_filter_params)
end
sig { params(hash: T::Hash[String, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
def symbolize_keys(hash)
hash.transform_keys(&:to_sym)
end
end
# typed: strict
# frozen_string_literal: true
class SaveReportService
extend T::Sig
Result = Struct.new(:success?, :report, :error_message)
sig { params(report_params: Types::WorkforceReportsController::TReportParams).returns(Result) }
def self.call(report_params)
new(report_params).call
end
sig { params(report_params: Types::WorkforceReportsController::TReportParams).void }
def initialize(report_params)
@report_params = report_params
end
sig { returns(Result) }
def call
filters_hash = extract_filters
return Result.new(false, nil, "Update default filters to save a report") if filters_hash.empty?
saved_report = create_saved_report(filters_hash)
if saved_report.save
Result.new(true, saved_report, nil)
else
Result.new(false, nil, "Failed to save report")
end
end
private
sig { returns(T::Hash[Symbol, T.untyped]) }
def extract_filters
@report_params.filters.to_hash.reject { |_, v| v.nil? || (v.respond_to?(:empty?) && v.empty?) }
end
sig { params(filters_hash: T::Hash[Symbol, T.untyped]).returns(SavedReport) }
def create_saved_report(filters_hash)
SavedReport.new(
report_key: @report_params.id,
user_id: @report_params.user_id,
name: @report_params.saved_name,
description: @report_params.saved_description,
http_method: @report_params.http_method,
path: @report_params.path,
params: filters_hash
)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment