我在我的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
如上所述,配方可以有多个IngredientLines,反之亦然。
我想避免的是在IngredienLine表上记录重复。
例如,想象一下,对于recipe_1,一个有{{measurement_unit_id“=>的IngredientLine; 1,“ingredient_id”=&gt; 1,“数量”=&gt; 3.5}是关联的,如果对于recipe_5,用户使用相同的值编译IngredientLine子表单,我不希望在IngredientLine表上有新记录,而只需要连接表中的新关联记录ingredient_lines_recipes。
请注意,目前我没有任何IngredientLine控制器,因为保存和更新IngredientLines由嵌套表单例程处理。甚至我的食谱控制器也很简单和标准:
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
我的猜测应该足以覆盖使用create
的IngredientLine的标准find_or_create
行为,但我不知道如何实现它。
但还有另外一个需要注意的重点,想象一下编辑一个包含一些IngredientLines的子表单,如果我添加另一个已存储在IngredientLine表中的IngredientLine,当然不应该在IngredientLine表上写任何东西,但是还应该区分已经与父项关联的子记录和需要创建关系的新子记录,在联接表上写一条新记录。
谢谢!
答案 0 :(得分:1)
在配方模型重新定义方法
def ingredient_lines_attributes=(attributes)
self.ingredient_lines << IngredientLine.where(attributes).first_or_initialize
end
答案 1 :(得分:1)
我遇到了类似的情况,并在this answer找到灵感。简而言之,我不担心嵌套模型的重复,直到节省时间。
翻译为您的示例,我将autosave_associated_records_for_ingredient_lines
添加到Recipe
。它贯穿ingredient_lines
并执行find_or_create
,正如你的直觉所说。如果ingredient_lines很复杂,Yuri的first_or_initialize
方法可能更清晰。
我相信这有你正在寻找的行为:嵌套模型永远不会重复,但编辑一个会导致新记录而不是更新共享记录。孤立ingredient_lines
的可能性很大,但如果这是一个严重问题,您可以选择更新,如果该模型只有一个recipe
的ID与当前ID匹配。
答案 2 :(得分:0)
老问题,但我遇到了同样的问题。忘了添加:id到带有rails 4 strong_parameters的白名单。
例如:
widgets_controller.rb
def widget_params
params.require(:widget).permit(:name, :foos_attributes => [:id, :name, :_destroy],)
end
widget.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