通过关系更新rails has_many [英] Updating rails has_many through relations
问题描述
我有模特
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
集合(即删除一些旧关系,并在需要时添加一些新关系).我应该更新关系的方法如下所示(在一些单独的服务中):
I want to update Specialization
collection (that is delete some of old relations and add a few new if needed). My method that should update relations looks like this (inside some separate service):
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
但是,与更新代理结合使用,这基本上没有任何作用-此确切的代码有效.我在做什么错了?
But this does basically nothing, however, in combination with updating agency - this exact code worked. What am I doing wrong?
在当前实现中,它发出错误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.
,这意味着它试图保存尚未删除旧关系的新关系,因此违反了相同条目的索引.
In current implementation it issues error 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.
So that means that it tries to save new relations having not yet deleted old ones, so it violates index of entries that are the same.
推荐答案
第一个解决方案:
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来完成这项工作.
In short, don't build anything. Let Rails do the job.
第二个解决方案:
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
都将首先销毁,然后最终重建.
It is the extension of your approach and should do the job. Note that in this case all specializations
are destroyed first and then rebuild eventually.
这篇关于通过关系更新rails has_many的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!