我有模特
class Agency < ActiveRecord::Base
has_many :specializations
has_many :cruise_lines, through: :specializations
end
class CruiseLine < ActiveRecord::Base
has_many :specializations
has_many :agencies, through: :specializations
end
class Specialization < ActiveRecord::Base
belongs_to :agency, inverse_of: :specializations
belongs_to :cruise_line, inverse_of: :specializations
end
我想更新Specialization
集合(即删除一些旧关系,并在需要时添加一些新关系)。我应该更新关系的方法看起来像这样(在一些单独的服务中):
def self.update_agency_specializations(agency, params)
attributes = params.require(:agency).permit( { cruise_line_ids: [] } )
attributes[:cruise_line_ids].select{ |x| x.to_i > 0 }.each do |cruise_line_id|
agency.specializations.build(cruise_line_id: cruise_line_id)
end
return false if agency.errors.present?
true
end
但是,这基本上没有与更新机构相结合 - 这个确切的代码有效。我做错了什么?
在当前实现中它发出错误ERROR: duplicate key value violates unique constraint "index_specializations_on_agency_id_and_cruise_line_id" DETAIL: Key (agency_id, cruise_line_id)=(1, 3) already exists.
这意味着它试图保存尚未删除旧关系的新关系,因此它违反了相同条目的索引。
答案 0 :(得分:6)
第一个解决方案:
def self.update_agency_specializations(agency, params)
attributes = params.require(:agency).permit( { cruise_line_ids: [] } )
agency.cruise_line_ids = attributes[:cruise_line_ids].select{ |x| x.to_i > 0 }
agency.save
end
!agency.errors.present?
end
简而言之,不要建造任何东西。让Rails完成这项工作。
第二个解决方案:
def self.update_agency_specializations(agency, params)
attributes = params.require(:agency).permit( { cruise_line_ids: [] } )
persisted = true
begin
Agency.transaction do
agency.specializations.destroy_all
attributes[:cruise_line_ids].select{ |x| x.to_i > 0 }.each do |cruise_line_id|
agency.specializations.build(cruise_line_id: cruise_line_id)
end
agency.save!
end
rescue RecordInvalid => e
persisted = false
end
persisted
end
这是你的方法的延伸,应该做的工作。请注意,在这种情况下,首先销毁所有specializations
,然后最终重建。