[英]rails validation of nested attributes for uniqueness when some may be marked for destroy
I've got the following (sanitized) models: 我有以下(消毒过的)模型:
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
The problem is as follows, 问题如下,
Lets say Person Joe Shmoe has two addresses currently attached to himself 让我们说人Joe Shmoe目前有两个地址附在自己身上
666 Foo Street, 12345 with unique id: “ABCDEFG” and 777 Lucky Avenue, 54321 with unique id: “GFEDCBA” 666 Foo Street,12345,唯一ID:“ABCDEFG”和777 Lucky Avenue,54321,唯一ID:“GFEDCBA”
And lets say that the following post comes through from a form: 并且让我们说以下帖子来自一个表单:
{: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}
}
The behavior appears to be that the second (ie the new) record is validated for uniqueness first, failing validation. 行为似乎是第二个(即新的)记录首先验证唯一性,验证失败。
The behavior I would like is to quite simply remove all elements that are marked_for_destruction?
我想要的行为是简单地删除所有
marked_for_destruction?
为marked_for_destruction?
元素marked_for_destruction?
before conducting any further validation. 在进行任何进一步验证之前
How can I rewire the lifecycle in this way? 如何以这种方式重新连接生命周期? Is there a better way to achieve this?
有没有更好的方法来实现这一目标?
Thanks! 谢谢!
I've solved this as follows: 我已经解决了这个问题如下:
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
Thus enforcing uniqueness, and preventing a person with invalid addresses from saving, but ignoring items that are marked for destruction. 因此,强制执行唯一性,并防止具有无效地址的人保存,但忽略标记为销毁的项目。 If anybody has had a similiar problem and has a better/algorithmically simpler/easier to read solution, and would like to share it, that would be awesome :D
如果有人遇到类似的问题,并且有更好的/算法更简单/更容易阅读的解决方案,并希望分享它,那将是非常棒的:D
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.