繁体   English   中英

具有嵌套属性和has_many:through关系的表单创建新记录,而不使用现有记录

[英]Form with nested attributes and has_many :through relationship create new record instead of using existing one


我想做的是给Plate一个简单的表格,您可以在其中选择所需的成分。 成分的数量和名称可能会因天而异。
每次创建一个新的板块时,它创建了4点新的选择plate_idingredient_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM