我有一个简单的表格,可以管理公司的职位。我使用accepts_nested_attributes
API来实现这一目标。用户可以使用加/减按钮添加/删除位置,并为每个按钮选择用户和位置。我要强制执行的一个验证是用户不能拥有同一公司的多个职位。我这样强制执行:
class User < ActiveRecord::Base
has_many :positions
end
class Position < ActiveRecord::Base
belongs_to :user
belongs_to :company
validates :title, presence: true
validates :user, presence: true
validates :company, presence: :true
validates :user, uniqueness: { scope: :company }
end
class Company < ActiveRecord::Base
has_many :positions
accepts_nested_attributes_for :positions, allow_destroy: true
end
但是,如果一个人被移除,我发现了一个错误 - 然后重新添加到同一家公司而没有保存。这个示例说明了问题:
company = Company.create(name: "Widgets")
mark = User.create(name: "Mark")
luke = User.create(name: "Luke")
mark_position = Position.create(company: company, user: mark, title: "CTO")
luke_position = Position.create(company: company, user: luke, title: "CFO")
company.positions_attributes = [
{ id: mark_position.id, _destroy: true },
{ id: john_position.id, _destroy: true },
{ user_id: mark.id, title: "CPO" },
{ user_id: john.id, title: "CMO" },
]
company.save!
验证失败:将用户重复的位置定位到公司以供用户
我是否可以做任何事情来允许这些更改而不会导致分配上的验证失败(我也在数据库级强制执行 - 这意味着这些会在服务器上引发5xx错误)?
答案 0 :(得分:0)
虽然它不漂亮 - 您可以覆盖positions_attributes=
来重新映射您的数据:
def positions_attributes=(attributes)
existing = Array(positions)
attributes.each do |iteration|
position = existing.find { |position| position.user_id.eql?(iteration[:user_id]) }
if position
attributes.select{ |iteration| iteration[:id].eql?(position.id) }.each{ |iteration| iteration.delete(:id) }
iteration[:id] = position.id
end
end
super attributes
end