2018/08/07
ActiveModel::Attributesでカスタムタイプを使う
Rails 5.2.0 で入ったActiveModel::Attributes API 最高ですよね。
でもカスタムタイプのドキュメントが見つからないんですよね。 ActiveRecord::Attributes API のカスタムタイプ ならあるのですが。
ソースコード見たところ簡単に作れるのがわかったので紹介します。
まず型の登録部分ですが、lib/active_model/type.rb で定義されています。
また、ActiveModelで使われているデフォルトタイプの実装を見ると cast_value
メソッドがあればよさそうです。
ActiveRecord::Attributes API と同様に実装します。
class MoneyType < ActiveModel::Type::Integer
def cast_value(value)
if !value.kind_of?(Numeric) && value.include?('$')
price_in_dollars = value.gsub(/\$/, '').to_f
super(price_in_dollars * 100)
else
super
end
end
end
# config/initializers/types.rb
ActiveModel::Type.register(:money, MoneyType)
# app/models/store_listing.rb
class StoreListing
include ActiveModel::Model
include ActiveModel::Attributes
attribute :price_in_cents, :money
end
store_listing = StoreListing.new(price_in_cents: '$10.00')
store_listing.price_in_cents # => 1000
このように ActiveModel::Attributes でカスタムタイプを使うことができます。