【问题标题】:Nested forms creates empty instances嵌套表单创建空实例
【发布时间】:2016-03-31 13:57:39
【问题描述】:

我有一个 Post 和一个 MaterielLink 模型。 一个帖子has_many materiel_linksaccepts_nested_attributes_for :materiel_links

我使用 gem cocoon 创建一个嵌套表单:在 post 表单上,我希望能够添加将在提交表单时创建的链接。

post/new.html.erb:

<%= simple_form_for @post, :html => { :id => "post_form", "data-post-id" => @post.id } do |f| %>
  <%= f.simple_fields_for :materiel_links do |materiel_link| %>
    <%= render 'materiel_link_fields', f: materiel_link %>
  <% end %>

  <%= link_to_add_association 'Ajouter', f, :materiel_links%> 
<% end %>

_materiel_link_fields.html.erb:

<%= f.fields_for :materiel_links do |materiel_link| %>
  <%= materiel_link.text_field :name %>
  <%= materiel_link.text_field :link %>
<% end %>

在我的后期控制器中:

 def update
    @materiel_links = @post.materiel_links.build(post_params[:materiel_links_attributes]

    if @post.update!(post_params)
      session[:current_draft_post_id] = nil
      redirect_to post_path(@post)
    else
      render :new
    end
  end

我在这里进行更新操作,因为由于特定于我的 rails 应用程序的原因,帖子是在呈现帖子/新页面时创建的(它被创建为空,用户只是更新它而不是实际创建它) .所以帖子已经存在,但不是我必须在更新操作中创建的 materiel_links。

还有参数:

def post_params
    params.require(:post).permit(:title, materiel_links_attributes: [:name,:link] )
end

我在更新操作中添加了一个 raise,但奇怪的是,当我输入 params 时,我可以找到我添加的每个 materiel_link 的链接/名称,但每对之前都有一个数字:

>> params
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"wqzWfaAcwrOOdxViYBO5HaV2bwsNsf5HsvDFEbBYapkOMAPXOJR7oT4zQHbc/hTW8T9a+iH5NRl1WUApxrIjkA==", "post"=>{"title"=>"my title", "materiel_links_attributes"=>{"1459431927732"=>{"materiel_links"=>{"name"=>"mon Lien 1", "link"=>"htttp1"}}, "1459431933881"=>{"materiel_links"=>{"name"=>" Mon lien 2", "link"=>"htttp2"}}}}, "controller"=>"posts", "action"=>"update", "id"=>"1250"}

但是当我输入 post_params 时, materiel_links 哈希中没有任何内容:

>> post_params
=> {"title"=>"my title","materiel_links_attributes"=>{"1459431927732"=>{}, "1459431933881"=>{}}}

MaterielLink 的实例已创建,但它们是空的:它们不保存链接/名称。

我哪里做错了?

【问题讨论】:

  • materiel_link have_many materiel_links吗?

标签: ruby-on-rails forms nested-forms cocoon-gem


【解决方案1】:

我的猜测是,因为在您的更新操作中,您在 .update 之前使用了 .build,它在某种程度上与 .update 冲突,因为 materiel_links 值再次传递到那里。您不再需要构建update 操作;但仅在edit 操作中,因为在调用.update(post_params) 时会自动创建/更新materiel_links,因为post_params 已经包含materiel_links 值。试试

def update
  if @post.update!(post_params)
    @materiel_links = @post.materiel_links

    session[:current_draft_post_id] = nil
    redirect_to post_path(@post)
  else
    render :new
  end
end

您还需要在强参数中将 materiel_link 的 ID 列入白名单,以便可以更新表单中的这些 materiel_link(如果只是创建,则不需要将 ID 列入白名单,无需更新)。您可能还希望允许破坏。更新如下:

def post_params
  params.require(:post).permit(:title, materiel_links_attributes: [:id, :name, :link, :_destroy] )
end

# post.rb
accepts_nested_attributes_for :materiel_links, allow_destroy: true

【讨论】:

  • 感谢您的回答。我应该指定由于特定于我的 rails 应用程序的原因,帖子是在呈现帖子/新页面时创建的(它是空的),所以用户只更新它。这就是为什么我使用更新操作而不是创建。而且,由于帖子是创建的,但不是 materiel_links,我不应该在更新操作中使用 .new 或 .build 吗?
  • .build 创建一个占位符关联对象。它还没有持久化到数据库中。它也只存储在内存中。大多数时候,您只在newedit 操作中使用.build。这样做的原因是.build 在调用该行之后将对象构建到内存中(假设.build 在edit 操作中调用),然后呈现edit 模板。但是在那个edit.html.erb 中,fields_for 已经为“构建”对象生成了字段。点击提交按钮后,参数现在将包含“构建”对象,准备好最终保存在数据库中
猜你喜欢
  • 2016-03-02
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 2020-10-22
  • 1970-01-01
相关资源
最近更新 更多