
[英]Rails 4: child record ID is saved but not its attributes, using nested form with has_many through relationship
[英]Form with nested attributes and has_many :through relationship create new record instead of using existing one
我想做的是给Plate一个简单的表格,您可以在其中选择所需的成分。 成分的数量和名称可能会因天而异。
每次创建一个新的板块时,它创建了4点新的选择plate_id
和ingredient_id
和布尔chosen
。
plate_id
是新盘创建和ingredient_id
应该是我的数据库中已有的成分的ID,并chosen
它,如果成分应在板。
这是我的课盘,选择和成分:
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
我的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 %>
最后是我的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
我的问题是,当我创建一个新盘子时,它会创建与所选名称相同的新食材(但当然具有不同的ID),而Choices会创建新食材。
我试图在嵌套属性中添加:id
:
params.require(:plate).permit(:name, choices_attributes: [:chosen, ingredient_attributes: [:id, :name]])
卜,当我这样做时,我会出错:
找不到ID = 1的配料
我搜索了答案,但找不到任何答案,我想我不知道Rails的参数,形式和嵌套属性足以理解问题所在。
谢谢你的帮助 !
ps:这是我关于堆栈溢出的第一个问题,如果我的问题有什么问题,请告诉我
您不需要accepted_nested_parameters_for :ingredient
因为该表单并非旨在允许您创建成分或编辑成分。
更好的是,您仅使用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 %>
然后您的属性应该是...
params.require(:plate).permit(:name, choices_attributes: [:chosen, :ingredient_id])
如果您只想显示成分,但不允许用户更改成分,则可以
<%= f.fields_for :choices do |fc| %>
<%= fc.check_box :chosen %>
<%= fc.hidden_field :ingredient_id %>
<%= Ingredient.find(fc.object.ingredient_id).name %>
<% end %>
您正在表单对象fc
包含的对象中找到Ingredient_id,并使用该ID访问Ingredient,并检索name属性。
还要注意:ingredient_id
...的隐藏字段,以确保它在属性哈希中返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.