通过关系更新rails has_many [英] Updating rails has_many through relations

查看:62
本文介绍了通过关系更新rails has_many的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有模特

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆