简体   繁体   English

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

[英]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_idingredient_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.

相关问题 Rails 4:使用具有has_many通过关系的嵌套形式保存子记录ID,但不保存其属性 - Rails 4: child record ID is saved but not its attributes, using nested form with has_many through relationship 通过关系在 has_many 中具有嵌套属性的 Rails 表单 - Rails form with nested attributes in has_many through relationship 嵌套表单以&#39;has_many到&#39;多对多关系创建许多新的关联对象 - Nested form to create a number of new associated objects in a 'has_many through' many to many relationship 使用has_many:through关系为现有子级创建新的父级记录 - Create new parent record with has_many :through relationship for existing children 使用嵌套形式的连接模型(has_many:through关系) - Using join model with nested form (has_many :through relationship) 使用accepts_nested_attributes_for将现有has_many记录添加到新记录 - Adding existing has_many records to new record with accepts_nested_attributes_for 如果新的活动记录具有属性,则创建一个 has_many 关联 - If new active record has attributes, then create a has_many association has_many通过从现有模型创建关系 - has_many through create relationship from existing models 与has_many的Rails嵌套形式:through关系 - rails nested form with has_many :through relationship 使用Rails更新has_many,:through关系中的额外属性 - Updating extra attributes in a has_many, :through relationship using Rails
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM