serializeを使うと柔軟にデータを保存できるようになって便利だが、バリデーションを書きづらいという問題がある。こういう場合は ActiveModel::Validations#read_attribute_for_validation
を使うとRailsのバリデーション機構を使いまわすことができる。
例えば File
モデルに data
属性があってそれがserializeされていて、 data
には "name"
"link"
というキーがあり、 "name"
は必須かつ長さ255以下、 "link"
は必須にしたいとする。そういう場合はこんな感じで書ける
app/models/file.rb
class File < ActiveRecord::Base
DATA_KEYS = %i(name link).freeze
serialize :data, Hash
validates :name, presence: true, length: { maximum: 255 }
validates :link, presence: true
def read_attribute_for_validation(key)
DATA_KEYS.include?(key) ? data[key] : super
end
end