4

我在我的 rails 3.2.3 应用程序中设置了一个嵌套表单,它工作正常,我的模型是:

class Recipe < ActiveRecord::Base
  attr_accessible :title, :description, :excerpt, :date, :ingredient_lines_attributes

  has_and_belongs_to_many :ingredient_lines
  accepts_nested_attributes_for :ingredient_lines
end

和:

class IngredientLine < ActiveRecord::Base
  attr_accessible :ingredient_id, :measurement_unit_id, :quantity

  has_and_belongs_to_many :recipes
  belongs_to :measurement_unit
  belongs_to :ingredient
end

如上所述,一个食谱可以有多个成分行,反之亦然。

我要避免的是 IngredienLine 表上的记录重复。

例如,假设对于 recipe_1 与 {"measurement_unit_id" => 1, "ingredient_id" => 1, "quantity" => 3.5} 的成分线相关联,如果对于 recipe_5,成分线子表单由用户使用相同的值编译,我不想在 IngredientLine 表上创建新记录,而只需要在 join 表成分_lines_recipes 中创建新的关联记录。

请注意,目前我没有任何成分线控制器,因为保存和更新成分线是由嵌套的表单例程处理的。甚至我的食谱控制器也是简单而标准的:

class RecipesController < ApplicationController
  respond_to :html

  def new
    @recipe = Recipe.new
  end

  def create
    @recipe = Recipe.new(params[:recipe])
    flash[:notice] = 'Recipe saved.' if @recipe.save  
    respond_with(@recipe)
  end

  def destroy
    @recipe = Recipe.find(params[:id])
    @recipe.destroy
    respond_with(:recipes)
  end

  def edit
    respond_with(@recipe = Recipe.find(params[:id]))
  end

  def update
    @recipe = Recipe.find(params[:id])
    flash[:notice] = 'Recipe updated.' if @recipe.update_attributes(params[:recipe])
    respond_with(@recipe)
  end

end

我的猜测是,应该足以用 覆盖createIngredientLine 的标准行为find_or_create,但我不知道如何实现它。

但是还有一点需要注意,想象一个存在一些成分线的子表单的编辑,如果我添加另一个成分线,它已经存储在成分线表中,轨道当然不应该在成分线表上写任何东西,但也应该区分已经与父关联的子记录,以及需要为其创建关系的新子记录,在连接表上写入新记录。

谢谢!

4

3 回答 3

2

老问题,但我有同样的问题。忘记使用 rails 4 strong_parameters 将 :id 添加到白名单。

例如:

widgets_controller.rb

def widget_params
  params.require(:widget).permit(:name, :foos_attributes => [:id, :name, :_destroy],)
end

小部件.rb

class Widget < ActiveRecord::Base
  has_many :foos, dependent: :destroy
  accepts_nested_attributes_for :foos, allow_destroy: true
end

foo.rb

class Foo < ActiveRecord::Base
  belongs_to :widget
end
于 2013-11-17T12:53:46.670 回答
2

在配方模型中重新定义方法

def ingredient_lines_attributes=(attributes)
   self.ingredient_lines << IngredientLine.where(attributes).first_or_initialize
end
于 2012-05-23T11:15:47.813 回答
1

我遇到了类似的情况,并在这个答案中找到了灵感。简而言之,在节省时间之前,我不担心嵌套模型的重复。

翻译成你的例子,我添加autosave_associated_records_for_ingredient_linesRecipe. 正如您的直觉所说,它遍历ingredient_lines并执行 a 。find_or_create如果成分线很复杂,尤里的first_or_initialize方法可能更干净。

我相信这具有您正在寻找的行为:嵌套模型永远不会重复,但编辑一个会导致新记录而不是更新共享的记录。孤儿的可能性很大,ingredient_lines但如果这是一个严重的问题,如果该模型只有一个recipeid 与当前模型匹配的模型,您可以选择更新。

于 2012-06-30T18:56:33.260 回答