使用update_attributes()和has_many:through关联时重复记录

时间:2011-11-11 18:13:41

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

我无法弄清楚为什么它会生成重复的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

Params看起来像

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

然后我做

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

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

1 个答案:

答案 0 :(得分:3)

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

  1. 包含&#39; id&#39;在已创建的每个属性中关联表中的行的行。这允许更新按预期工作。
  2. 使用skill_id属性上的复选框。因此,如果未选中该复选框,则skill_id将不会显示在params散列中。然后,我运行这段代码
  3. params[:recruit_profile][:recruit_profiles_skills_attributes].map{ |rps| if rps[:skill_id].nil? then rps[:_destroy] = 1 end }

    这段代码将检查是否设置了:skill_id。如果未设置,则需要删除该行。删除条目的方法,即使:allow_destroy设置为true,也是附加&#34;:_ destroy =&gt; 1&#34; key =&gt;哈希值。因此,:id将出现,并且:_destroy将存在,因此update_attributes将删除它。

    执行上述操作将允许create(:id not present,但:skill_id present),update(:id present和:skill_id present)和destroy(:id present,但:skill_id not present)。恕我直言,这不是它应该如何运作,但是这项工作只需要额外增加1行代码(由于长度分成3行)。

    (注意:用你的关联表中的其他参数替换skill_id。只有当你使用具有多个属性的关联表时才需要这个方法。否则,经典的collection_ids = [#,#, #]仍然适用于has_many:通过关联。)