ActiveModel::Attributes POROの属性をネイティブ型のまま保存するAPI

UI層から送られてきたparamsを、期待する属性のままデータベースに保存させるためのAPI

POROなクラスでparamsを処理する時、通常だとデータがstringとして保存されてしまう。

例えば、勤務時間のレポートを作るクラスがあるとする。

ユーザーがフォームに出勤時間、退勤時間、ノルマを入力し、コントローラーに送られてきた値をWorkTimeReportのインスタンスが処理している。

class WorkTimeReport
  attr_accessor :start_date, :end_date, :min_items

  def initialize(params = {})
    @start_date = params[:start_date]
    @end_date = params[:end_date]
    @min_items = params[:min_items]
  end

  def run!
    # 何かを実行する
  end
end

report = WorkTimeReport.new(start_date: "2022-01-01", end_date: "2022-03-01", min_items: "10")

# しかしデータがstringとして保存されてしまう。。
report.start_date
# => "2022-01-01"
report.min_items
# => "10"

Date型で保存されて欲しいのに、String型で保存されてしまう。

そんな時に、ActiveModel::AttributesというAPIが使える。

ActiveModel::Attributesをミックスインすると、保存されるデータの型を明示させることができる。

class WorkTimeReport
  include ActiveModel::Model
  include ActiveModel::Attributes

  attribute :start_date, :date
  attribute :end_date, :date
  attribute :min_items, :integer

  def run!
    *#何かを実行する*
  end
end

report = SalesReport.new(start_date: "2022-01-01", end_date: "2022-03-01", min_items: "10")

*# 属性がネイティブ型になってくれた*
report.start_date
*# => Sat, 01 Jan 2022*

report.min_items
*# => 10*

Railsの技: Attributes APIでPOROの属性を自動的にキャストする(翻訳)|TechRacho by BPS株式会社

ActiveRecord::Attributes::ClassMethods