【问题标题】:Duplicate records when using update_attributes() and a has_many :through association使用 update_attributes() 和 has_many 时重复记录:通过关联
【发布时间】:2011-12-27 05:51:30
【问题描述】:

我不明白为什么它会生成重复的recruit_profiles_skills 而不是更新

class RecruitProfile < ActiveRecord::Base
   has_many :skills, :through => :recruit_profiles_skills
   has_many :recruit_profiles_skills, :dependent => :destroy
   accepts_nested_attributes_for :recruit_profiles_skills, :allow_destroy => true

class Skill < ActiveRecord::Base
    has_many :recruit_profiles, :through => :recruit_profiles_skills
    has_many :recruit_profiles_skills, :dependent => :destroy

参数看起来像

"recruit_profile"=>{
    "recruit_profiles_skills_attributes"=>[{"skill_id"=>"1", "level"=>"15"}]
}

那我做

def update
    @recruit_profile.update_attributes(params[:recruit_profile])

但是,这会创建重复的关联记录。为什么这不只是更新!? 我可以使用验证来防止重复,但是它永远不会更新,因为它只是想创建一个新记录,但是新记录是无效的,因为它没有通过验证。

【问题讨论】:

  • 我更新了问题。这是我得到重复的关联记录。
  • 您可以尝试将RecruitProfilesSkills:id 作为参数传递给recruit_profile_skills_attributes 吗?该文档使我相信,如果它不包含属性哈希中的 id,它将创建一个新记录。
  • 这将允许更新当前的关联记录,但是如果我想删除一些,添加一些并一次更改一些呢?我希望能够为 has_many 做:通过,就像我对 habtm 所做的一样。使用 habtm,我可以只 update_atrb(skill_ids) 它将删除不再存在的技能 ID 的关联,并为技能 ID 添加新的关联是新的。如果我使用与上面相同的参数进行更新并添加“:id =>”,那么它只会更新现有记录并添加新记录,但不会删除不存在的记录。我说得通吗?
  • 也许我对 Rails 的要求太多了...我实际上有一个辅助方法可以按照我的意愿进行操作,但我只是假设 rails 的行为类似于 HABTM 关联的 :through 关联.
  • 你想要什么都有意义。我正在查看的文档是here。如果您查看 _destroy 部分,它会描述您想要的我的想法。

标签: ruby-on-rails-3 activerecord associations has-many-through


【解决方案1】:

我在代码中解决这个问题的方法是:

  1. 在已创建的每个属性中包含关联表中行的“id”。这允许更新按预期工作。
  2. 在 Skill_id 属性上使用复选框。因此,如果未选中该复选框,则 Skill_id 将不会显示在 params 哈希中。然后,我运行这段代码



params[:recruit_profile][:recruit_profiles_skills_attributes].map{ |rps| 
    if rps[:skill_id].nil? then rps[:_destroy] = 1 end 
}

那段代码将检查是否设置了 :skill_id。如果未设置,则需要删除该行。删除条目的方法,即使 :allow_destroy 设置为 true,也是将 ":_destroy => 1" key=>value 附加到散列。因此, :id 将存在,并且 :_destroy 将存在,因此 update_attributes 将删除它。

执行上述操作将允许创建(:id 不存在,但 :skill_id 存在)、更新(:id 存在和 :skill_id 存在)和销毁(:id 存在,但 :skill_id 不存在)。恕我直言,这不是它应该如何工作的,但这项工作只需要额外的 1 行代码即可完成(由于长度原因分为 3 行)。

(注意:用关联表中的任何其他参数替换技能ID。仅当您使用具有多个属性的关联表时才需要这种循环方式。否则,经典的collection_ids = [#,#,#]仍然可以与 has_many 一起使用:通过关联。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    相关资源
    最近更新 更多