通过关联删除has_many删除该id的所有关联

时间:2014-06-04 15:15:13

标签: ruby-on-rails ruby-on-rails-4

这是几个星期前的工作,但在添加paper_trail版本后,我现在在进行更新时遇到以下错误。

Miniature通过Sculptings表有许多雕塑家。当我通过删除关联的Sculptor编辑Miniature然后提交更新时,Miniatures Controller会破坏属于已移除的Sculptor的Sculptings表中的所有条目,而不仅仅是更新的Miniature的条目。

这是我的微型更新操作

def update
    @miniature = Miniature.find(params[:id])
     if params[:miniature][:"release_date(2i)"] == ''
      # no month is given, insert fake month and day
      params[:miniature][:"release_date(2i)"] = '1'
      params[:miniature][:"release_date(3i)"] = '1'
      mask = 4 # 100
    elsif params[:miniature][:"release_date(3i)"] == ''
      # no day is given, insert a fake day
      params[:miniature][:"release_date(3i)"] = '1'
      mask = 6 # 110
    else
      # full-date
      mask = 7 # 111
    end
    if params[:sculptors][:id]
      ## Convert ["", "1","2","4","8"] to [1,2,4,8]
      params[:sculptors][:id] = params[:sculptors][:id].reject(&:empty?).map(&:to_i) 
      ## Get the sculptor_id from sculptings already present in database [1,2,5,6] 
      old_sculptors = @miniature.sculptings.pluck(:sculptor_id)
      ## Find the new sculptors to be added [1,2,4,8] - [1,2,5,6] = [4,8]
      new_sculptors = params[:sculptors][:id] - old_sculptors 
      ## Find the old_sculptors to be deleted [1,2,5,6] - [1,2,4,8] = [5,6]
      old_sculptors = old_sculptors - params[:sculptors][:id] 
      ## Build new_sculptors [4,8]
      new_sculptors.each do |sculptor|
        @miniature.sculptings.build(:sculptor_id => sculptor)
      end
      ## Delete old_sculptors [5,6]
      Sculpting.destroy_all(:sculptor_id => old_sculptors)
    end
    if @miniature.update_attributes(miniature_params.merge(date_mask: mask))
      flash[:success] = "Miniature updated. #{undo_link}"
      redirect_to @miniature
    else
      render 'edit'
    end
  end

以下是表单的相关位(它使用多选)。

<div class="control-group">
        <%= f.fields_for(@sculpting) do |scf| %>
          <%= scf.label :sculptors, 'Sculpted by', class: "control-label" %>
            <div class="controls">
              <%= collection_select( :sculptors, :id, @all_sculptors, :id, :fullname, 
                   {:selected => @miniature.sculptors.map(&:id)}, 
                   {class: 'multiselect', multiple: true}) %>
            </div>
        <% end %>
      </div>

以下是更新的日志输出,其中我所做的就是从Miniature 43中移除与Sculptor 6的关联,但正如您所看到的,它还删除了与Sculptor 6的所有其他关联,即使用Miniatures 42和41。 / p>

Started PATCH "/miniatures/43" for 127.0.0.1 at 2014-06-04 15:43:57 +0100
Processing by MiniaturesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"xnfOwotMS39buQFCYnUqZTvFajc0hlz+LIVo4cN02q0=", "miniature"=>{"name"=>"A Aa Perry", "material"=>"Hard Plastic", "pcode"=>"", "release_date(1i)"=>"", "release_date(2i)"=>"", "release_date(3i)"=>"", "set"=>"0", "quantity"=>"", "random"=>"0", "notes"=>"", "comment"=>"Removed sclptr"}, "manufacturers"=>{"id"=>["", "1"]}, "scales"=>{"id"=>["", "3"]}, "sculptors"=>{"id"=>[""]}, "commit"=>"Save changes", "id"=>"43"}

  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 4 ORDER BY "users"."id" ASC LIMIT 1

  Miniature Load (0.3ms)  SELECT "miniatures".* FROM "miniatures" WHERE "miniatures"."id" = ? LIMIT 1  [["id", "43"]]

   (0.4ms)  SELECT "sculptings"."sculptor_id" FROM "sculptings" WHERE "sculptings"."miniature_id" = ?  [["miniature_id", 43]]
  Sculpting Load (0.5ms)  SELECT "sculptings".* FROM "sculptings" WHERE "sculptings"."sculptor_id" IN (6)

   (0.1ms)  begin transaction
  SQL (0.5ms)  DELETE FROM "sculptings" WHERE "sculptings"."id" = ?  [["id", 46]]
  SQL (0.5ms)  INSERT INTO "versions" ("created_at", "event", "item_id", "item_type", "object", "whodunnit") VALUES (?, ?, ?, ?, ?, ?)  [["created_at", Wed, 04 Jun 2014 14:43:57 UTC +00:00], ["event", "destroy"], ["item_id", 46], ["item_type", "Sculpting"], ["object", "---\nid: 46\nsculptor_id: 6\nminiature_id: 41\ncreated_at: 2014-06-04 11:17:26.000000000 Z\nupdated_at: 2014-06-04 11:17:26.000000000 Z\n"], ["whodunnit", 4]]
  PaperTrail::Version Load (0.1ms)  SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = ? AND "versions"."item_type" = ? ORDER BY versions.created_at ASC, versions.id ASC  [["item_id", 46], ["item_type", "Sculpting"]]
   (3.6ms)  commit transaction

   (0.2ms)  begin transaction
  SQL (0.4ms)  DELETE FROM "sculptings" WHERE "sculptings"."id" = ?  [["id", 47]]
  SQL (0.3ms)  INSERT INTO "versions" ("created_at", "event", "item_id", "item_type", "object", "whodunnit") VALUES (?, ?, ?, ?, ?, ?)  [["created_at", Wed, 04 Jun 2014 14:43:57 UTC +00:00], ["event", "destroy"], ["item_id", 47], ["item_type", "Sculpting"], ["object", "---\nid: 47\nsculptor_id: 6\nminiature_id: 42\ncreated_at: 2014-06-04 14:42:07.000000000 Z\nupdated_at: 2014-06-04 14:42:07.000000000 Z\n"], ["whodunnit", 4]]
  PaperTrail::Version Load (0.1ms)  SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = ? AND "versions"."item_type" = ? ORDER BY versions.created_at ASC, versions.id ASC  [["item_id", 47], ["item_type", "Sculpting"]]
   (3.3ms)  commit transaction

   (0.1ms)  begin transaction
  SQL (0.4ms)  DELETE FROM "sculptings" WHERE "sculptings"."id" = ?  [["id", 48]]
  SQL (0.3ms)  INSERT INTO "versions" ("created_at", "event", "item_id", "item_type", "object", "whodunnit") VALUES (?, ?, ?, ?, ?, ?)  [["created_at", Wed, 04 Jun 2014 14:43:57 UTC +00:00], ["event", "destroy"], ["item_id", 48], ["item_type", "Sculpting"], ["object", "---\nid: 48\nsculptor_id: 6\nminiature_id: 43\ncreated_at: 2014-06-04 14:42:31.000000000 Z\nupdated_at: 2014-06-04 14:42:31.000000000 Z\n"], ["whodunnit", 4]]
  PaperTrail::Version Load (0.1ms)  SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = ? AND "versions"."item_type" = ? ORDER BY versions.created_at ASC, versions.id ASC  [["item_id", 48], ["item_type", "Sculpting"]]
   (2.5ms)  commit transaction

   (0.1ms)  begin transaction
   (0.2ms)  commit transaction
  PaperTrail::Version Load (0.4ms)  SELECT "versions".* FROM "versions" WHERE "versions"."item_id" = ? AND "versions"."item_type" = ? ORDER BY versions.created_at DESC, versions.id DESC LIMIT 1  [["item_id", 43], ["item_type", "Miniature"]]
Redirected to http://localhost:3000/miniatures/43
Completed 302 Found in 166ms (ActiveRecord: 15.9ms)

就像我说的那样,几周前这一切都完美无缺,但从那以后我添加了很多paper_trail版本,我真的不想恢复到旧版本。我也不确定问题出在哪里。在我工作之后被困在这上面非常令人沮丧。非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

重新阅读并重新阅读更新操作后,我认为可能就行了

Sculpting.destroy_all(:sculptor_id => old_sculptors)

不再局限于

定义的雕刻线
old_sculptors = @miniature.sculptings.pluck(:sculptor_id)

并且可能需要再次限制当前的@miniature。

我把它改成了

Sculpting.where(:miniature_id => @miniature.id).destroy_all(:sculptor_id => old_sculptors)

问题解决了。

我很确定它最初是按照预期的方式工作但现在似乎无法实现。它一定是马车。无论如何,问题似乎解决了。