当某些属性可能被标记为销毁时,对嵌套属性的唯一性进行 Rails 验证



我有以下(净化)模型:

 class Person < ActiveRecord::Base
      attr_accessible :name, :first_name, :last_name, :age, :job_title, :salary, :ssn, :prison_convictions, :addresses_attributes
      has_many :addresses, inverse_of: :person
      accepts_nested_attributes_for :addresses, allow_destroy: true
 end

 class Address < ActiveRecord::Base
      attr_accessible :zip_code, :street,:house_number,
 :unique_per_person_government_id
      belongs_to :person, inverse_of: :addresses
      validates_uniqueness_of :unique_per_person_government_id, scope: :person_id
 end

问题如下,

假设人Joe Shmoe目前有两个地址附在自己身上

666 Foo Street, 12345 唯一 ID: "ABCDEFG"和777幸运大道,54321,唯一ID:"GFEDCBA"

假设以下帖子来自一个表单:

 {:addresses_attributes =>
 { [0] => {:unique_per_person_government_id => “ABCDEFG”, :street=> “Foo Street”, :house_number => 666, :zip_code=>12345, _destroy => 1}
 [1] => {:unique_per_person_government_id => “ABCDEFG”, :street=>”Bar Street”, :house_number => 888, :zip_code => 12345, _destroy => 0}
 }

该行为似乎是第二条(即新)记录首先验证唯一性,验证失败。

我想要的行为是在进行任何进一步验证之前非常简单地删除marked_for_destruction?的所有元素。

如何以这种方式重新连接生命周期?有没有更好的方法来实现这一目标?

谢谢!

我已经解决了这个问题,如下所示:

class Person < ActiveRecord::Base
  attr_accessible :name, :first_name, :last_name, :age, :job_title, :salary, :ssn, :prison_convictions, :addresses_attributes
  has_many :addresses, inverse_of: :person
  accepts_nested_attributes_for :addresses, allow_destroy: true
  def validate_addresses
    codes = {}
    addresses.each do |a|
      if codes.key?(a.unique_per_person_government_id) and not a.marked_for_destruction?
        codes[a.unique_per_person_government_id] = codes[a.unique_per_person_government_id]+1
        if codes[a.unique_per_person_government_id] > 1
          return false
        end
      elsif not codes.key?(a.unique_per_person_government_id) and a.marked_for_destruction?
        codes[a.code] = 0
      elsif not codes.key?(a.unique_per_person_government_id) and not a.marked_for_destruction?
        codes[dacode] = 1
      end
    end
    return true
  end
end

class Address < ActiveRecord::Base
  before_save :validate_addresses
  attr_accessible :zip_code, :street,:house_number, :unique_per_person_government_id
  belongs_to :person, inverse_of: :addresses
  validates_uniqueness_of :unique_per_person_government_id, scope: :person_id, unless: :skip_validation?
  def skip_validation?
    person.addresses.each do |a|
      if unique_per_person_government_id == a.code and id != a.id
        return false unless a.marked_for_destruction?
      elsif id == a.id and a.marked_for_destruction?
        return false
      end
    end
    return true
  end
end

从而强制执行唯一性,并防止地址无效的人保存,但忽略标记为销毁的项目。如果有人遇到过类似的问题,并且有一个更好/算法更简单/更容易阅读的解决方案,并且想分享它,那将是很棒的:D

相关内容

  • 没有找到相关文章

最新更新