※ composed_of を使用した方がスマートに解決できるようです。詳しくは @jnchito さんのコメントをご覧ください。
ActiveRecord でカラムの値を取得するとき、普通はもちろん DB に格納されている値を
取得することになるんですが、Float の値を Value Object に変換して取得したいときがありました。
そんなときは、カラム名のメソッドを作れば解決できます。
メソッド内で元の値を取得する時は read_attribute()
を使用しましょう。
# coding: utf-8
class User < ActiveRecord::Base
# user.rate でレコードの値を直接取得せず、
# Rating オブジェクトに変換したものを取得している
def rate
# レコードの rate の値は read_attribute() で取得
@rate ||= Rating.new(read_attribute(:rate))
end
end
さて、これを定義した場合に困るのが validates です。
validates :rate
と記述した際、値に対してバリデーションをかけたいのに、
Rating
オブジェクトに対してかかってしまいます。
そんな場合には生データを取得するためのメソッドも用意して、
そっちにバリデーションをかけましょう。
# coding: utf-8
class User < ActiveRecord::Base
validates :raw_rate,
format: {with: /\A\d+(\.\d{1,2})?\z/},
numericality: {more_than_or_equal_to: 0, less_than_or_equal_to: 100}
def raw_rate
read_attribute(:rate)
end
end
少し回りくどいですが、これでデータを Valude Object で取得できました。
データ取得時に何らかの前後処理を入れたいときにもこの方法を利用できると思います。
もっと良い方法があれば是非コメントください。