Rails 8.1, Ruby 4.0, отчёты из ClickHouse. Параметры ходят хэшем через пять классов:
options = {
from: params[:from],
to: params[:to],
group_by: params[:group_by] || "day",
currency: "RUB"
}
ReportQuery.new(options).call
ReportExporter.new(options.merge(format: "xlsx")).call
Полдня искал баг, а это была опечатка options[:form] вместо :from, которая молча вернула nil. Хочу объект с явными полями. Struct или Data, и где делать значения по умолчанию?
Data, раз параметры после создания не меняются. Значения по умолчанию и проверки удобно делать в своём initialize, а super без аргументов передаст дальше все именованные:
ReportParams = Data.define(:from, :to, :group_by, :currency) do
def initialize(from:, to:, group_by: "day", currency: "RUB")
unless %w[day week month].include?(group_by)
raise ArgumentError, "unknown group_by: #{group_by}"
end
super
end
end
report = ReportParams.new(from: Date.new(2026, 1, 1), to: Date.new(2026, 1, 31))
report.group_by # => "day"
report.with(currency: "USD") # новый объект, старый не меняется
report.form # NoMethodError вместо тихого nil
Подробно про Data есть в документации: https://docs.ruby-lang.org
Я бы в том же initialize ещё проверял, что from не позже to, это самая частая ошибка в отчётах. А строки из формы в даты пусть приводит контроллер или форм-объект. Data лучше получать уже готовые значения, иначе он начнёт знать про формат параметров.
а чем Data тогда отличается от Struct, кроме того что поля нельзя менять? когда что брать?