Rails3系統でaccepts_nested_attributes_forでネストしたパラメータでuniqueness validationが適用されなかった
accepts_nested_attributes_forでネストして、フォームから送られてくるパラメータ上で値が重複してもDBに保存されていな限りvalidationができなかった
下記のような状態だと不可能
class User < ActiveRecord::Base has_many :emails accepts_nested_attributes_for :emails end
class Email < ActiveRecord::Base belongs_to :user validates :address, uniqueness: true end
フォームから送られてくる値は以下
{ "user" => { "name" => "hogehoge", "emails_attributes" => { "0" => {"address" => "hoge@example.com"}, "1" => {"address" => "hoge@example.com"} } }
DBに保存されたものとフォームから重複して送られてくるもの両方をカバーする
class User < ActiveRecord::Base has_many :emails accepts_nested_attributes_for :emails validates_each :emails do |record, attr, value| record.errors.add(attr, "が重複しています") if record.nested_uniq?(value, [:address]) end def nested_uniq?(records, attrs) attrs = attrs.map(&:to_s) nested_records = records.map do |record| record.attributes.values_at(*attrs).compact end nested_records.size != nested_records.uniq.size end end
class Email < ActiveRecord::Base belongs_to :user validates :address, uniqueness: true end
ActiveModel::EachValidatorを継承したものを使って汎用的なカスタムバリデータを実装するのほうがいいかもしれない