更新HABTM模型关联仅删除关联

时间:2014-06-12 07:19:33

标签: ruby-on-rails ruby-on-rails-4 rails-activerecord has-and-belongs-to-many

创建新的HABTM关联对我来说很合适,但每次我尝试更新它们时,所有关联都会被删除。

这就是我的更新操作的样子。

def update
    params[:dish][:cuisine_ids] ||= []
    params[:dish][:diet_ids] ||= []

    @user = current_user
    @dish = @user.dishes_selling.find_by(:id => params[:id])

    @dish.cuisines = Cuisine.where(:id => params[:dish][:cuisine_ids]) ### (1) ###
    @dish.diets = Diet.where(:id => params[:dish][:diet_ids]) ### (1) ###

    if @dish
        respond_to do |format|
          if @dish.update(dish_params) ### (2) ###
            format.html { redirect_to dish_path(@dish), notice: 'Dish was edited.' }
          else
            format.html { render action: 'edit' }
          end
        end
    else
        flash[:error] = "You can only edit your dish!"
        render :index
    end
end

我的菜肴看起来像这样

    def dish_params
      params.require(:dish).permit(:title, :desc, cuisine_ids: [:id], diet_ids: [:id])
    end

如果在编辑时我单击两个菜单复选框,则在步骤(2)中的日志读取此内容(仅注意Delete且不更新或插入cuisine_dishes表)

(0.1ms)  begin transaction
  SQL (0.4ms)  DELETE FROM "cuisines_dishes" WHERE "cuisines_dishes"."dish_id" = ? AND "cuisines_dishes"."cuisine_id" IN (7, 9)  [["dish_id", 61]]
  SQL (0.2ms)  UPDATE "dishes" SET "desc" = ?, "updated_at" = ? WHERE "dishes"."id" = 61  [["desc", "yema1245"], ["updated_at", "2014-06-12 06:57:36.622811"]]
   (5.5ms)  commit transaction
Redirected to http://localhost:3000/dishes/61
Completed 302 Found in 48ms (ActiveRecord: 13.7ms) 

问题:为什么更新HABTM关联尝试删除关联,而不是尝试创建新关联(如果它们以前不存在),如果以前存在但是不再删除,则删除。< / p>

2 个答案:

答案 0 :(得分:3)

你应该尝试使用&lt;&lt;运算符而不是=;

@dish.cuisines << Cuisine.where(:id => params[:dish][:cuisine_ids]).last

这应该添加而不是替换两个表中所需的ID。

答案 1 :(得分:2)

我认为答案源于我的问题:

  

为什么要更新HABTM关联

更新HABTM关联是什么意思?


<强> HABTM

HABTM关联是collection of records,可以添加(<<)或删除(.delete)。你无法用这个“更新”记录 - 你必须添加或删除(主要是因为他们没有primary keys

我们这样做:

#app/controllers/your_controller.rb
def update
   @obj = Model.find params[:id]
   @obj2 = Model2.find params[:model_2]

   @obj.asssociative_data << @obj2
end

您遇到的问题是您将新数据传递给habtm关联。您可以“更新”此数据的唯一方式是使用您发布的新ids覆盖所有当前集合(这是我认为您正在做的事情)


<强>修正

解决此问题的方法是确保您使用cuisine_ids: [:id]diet_ids: [:id] strong_params方法传递正确的参数。

我认为你的问题是你只会传递:id。我认为Rails希望你传递:cuisine_ids:diet_ids,这些数组只填充数字数据,就像我们的代码一样:

def profile_params
    params.require(:profile).permit(attributes(Profile), :image, :category_ids)
end

为此,您必须使用表单执行此操作:

<%= f.select(:category_ids, Category.all, prompt: "Category") %>