[英]Form with nested attributes and has_many :through relationship create new record instead of using existing one
What I try to do is a simple form for Plate where you can choose which Ingredients you want. 我想做的是给Plate一个简单的表格,您可以在其中选择所需的成分。 The number and name of Ingredients may vary by day.
成分的数量和名称可能会因天而异。
Every time a new Plate is created, it created 4 new Choices with plate_id
and ingredient_id
and a boolean chosen
. 每次创建一个新的板块时,它创建了4点新的选择
plate_id
和ingredient_id
和布尔chosen
。
plate_id
is from the new plate create and ingredient_id
should be the id of the already existing ingredient in my database, and chosen
it's if the ingredient should be in the plate. plate_id
是新盘创建和ingredient_id
应该是我的数据库中已有的成分的ID,并chosen
它,如果成分应在板。
Here is my classes Plate, Choice and Ingredient : 这是我的课盘,选择和成分:
class Plate < ActiveRecord::Base
has_many :choices
has_many :ingredients, through: :choices
accepts_nested_attributes_for :choices
end
class Choice < ActiveRecord::Base
belongs_to :plate
belongs_to :ingredient
accepts_nested_attributes_for :ingredient
end
class Ingredient < ActiveRecord::Base
has_many :choices
has_many :plates, through: :choices
end
And my Plate nested form looks like this : 我的Plate嵌套表格如下所示:
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%= f.fields_for :choices do |fc| %>
<%= fc.check_box :chosen %>
<%= fc.fields_for :ingredient do |fi| %>
<%= fi.text_field(:name)%> <br />
<% end %>
<% end %>
And finally my Plate controller : 最后是我的Plate控制器:
def new
@plate = Plate.new
@choice1 = @plate.choices.build
@choice2 = @plate.choices.build
@choice3 = @plate.choices.build
@choice4 = @plate.choices.build
@ingredient1 = Ingredient.find_by_name('peach')
@ingredient2 = Ingredient.find_by_name('banana')
@ingredient3 = Ingredient.find_by_name('pear')
@ingredient4 = Ingredient.find_by_name('apple')
@choice1.ingredient_id = @ingredient1.id
@choice2.ingredient_id = @ingredient2.id
@choice3.ingredient_id = @ingredient3.id
@choice4.ingredient_id = @ingredient4.id
end
def plate_params
params.require(:plate).permit(:name, choices_attributes: [:chosen, ingredient_attributes: [ :name]])
end
My problem is that when I create a new plate, it create new ingredients with same name as the chosen one (but with different id of course) and Choices had the ingredient_id of the new ingredients created. 我的问题是,当我创建一个新盘子时,它会创建与所选名称相同的新食材(但当然具有不同的ID),而Choices会创建新食材。
I tried to add the :id
in the nested attributes : 我试图在嵌套属性中添加
:id
:
params.require(:plate).permit(:name, choices_attributes: [:chosen, ingredient_attributes: [:id, :name]])
Bu when I do that, I go an error : 卜,当我这样做时,我会出错:
Couldn't find Ingredient with ID=1 for Choice with ID=
找不到ID = 1的配料
I searched for answers but couldn't find any, I guess I don't know Rails params, form and nested attributes enough to understand where is the problem. 我搜索了答案,但找不到任何答案,我想我不知道Rails的参数,形式和嵌套属性足以理解问题所在。
Thanks for your help ! 谢谢你的帮助 !
ps : It's my first question on Stack Overflow, please let my know if anything is wrong with my question ps:这是我关于堆栈溢出的第一个问题,如果我的问题有什么问题,请告诉我
You don't need accepted_nested_parameters_for :ingredient
since the form isn't designed to let you create ingredients or edit ingredients. 您不需要
accepted_nested_parameters_for :ingredient
因为该表单并非旨在允许您创建成分或编辑成分。
Better that you just use collection_select
to select an existing ingredient as part of the choice
record (that is, just save the ingredient_id). 更好的是,您仅使用
collection_select
来选择现有成分作为choice
记录的一部分(也就是说,只需保存Ingredient_id)。
<%= f.fields_for :choices do |fc| %>
<%= fc.check_box :chosen %>
<%= fc.collection_select(:ingredient_id, Ingredient.all, :id, :name, prompt: true) %>
<% end %>
And your attributes should then be... 然后您的属性应该是...
params.require(:plate).permit(:name, choices_attributes: [:chosen, :ingredient_id])
If you just want to show the ingredient but not allow the user to change which ingredient, you can do 如果您只想显示成分,但不允许用户更改成分,则可以
<%= f.fields_for :choices do |fc| %>
<%= fc.check_box :chosen %>
<%= fc.hidden_field :ingredient_id %>
<%= Ingredient.find(fc.object.ingredient_id).name %>
<% end %>
You're finding the ingredient_id in the object encompassed by the form object fc
and using that id to access the Ingredient, and retrieving the name attribute. 您正在表单对象
fc
包含的对象中找到Ingredient_id,并使用该ID访问Ingredient,并检索name属性。
Also notice the hidden field for the :ingredient_id
... to make sure it's returned in the attribute hash. 还要注意
:ingredient_id
...的隐藏字段,以确保它在属性哈希中返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.