【问题标题】:Rails Nested Form - edit action & edit.html.erb won't display the form or related post contentRails 嵌套表单 - 编辑操作和 edit.html.erb 不会显示表单或相关的帖子内容
【发布时间】:2016-02-19 18:34:29
【问题描述】:

我制作了一个表单,用户可以通过单击文本或 url 按钮动态添加嵌套表单字段。提交表单后,内容将显示在视图模板中。但是,当我在/posts/id/edit 编辑(希望然后更新)帖子时,帖子内容不会出现在编辑视图模板中 - 它是浏览器中的空白页面。

log of SQL

非常感谢您的帮助!谢谢!

后模型

class Post < ActiveRecord::Base
  has_many :things, dependent: :destroy
  accepts_nested_attributes_for :things
end 

事物模型

class Thing < ActiveRecord::Base
  belongs_to :post
end 

架构

create_table "posts", force: :cascade do |t|
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end

create_table "things", force: :cascade do |t|
 t.text     "text"
 t.string   "url"
 t.integer  "post_id"
end

帖子控制器

class PostsController < ApplicationController

def edit
    @post = Post.find(params[:id])
end 

def update
end 

new.html.erb

 <button id='addtext'>text</button>
 <button id='addurl'>url</button>

 <%= form_for @post, url: posts_path, html: { multipart: true } do |f| %>

 <%= f.fields_for :thing do |ff| %>
 <% end %> 
 <%= f.submit %>
 <% end %>

posts.coffee

 current_index = 0

 addText = ->
 html = """
 <div>
 <textarea placeholder="Write something..."     name="post[things_attributes][#{current_index}][text]"     id="post_things_attributes_#{current_index}_text"></textarea>
 <input type="hidden" name="post[things_attributes][#{current_index}]    [order]" id="post_things_attributes_#{current_index}_order" value="#{current_index}" />
 </div>
 """

$("#new_post input[type='submit']").before(html)
current_index += 1

$ ->
$('#addtext').on('click', addText)


current_index = 0

【问题讨论】:

  • 你应该有一个名为 edit.html.erb 的视图
  • 抱歉 - 我愿意,它的代码与 new.html.erb 模板中的代码相同。

标签: javascript ruby-on-rails ruby forms ruby-on-rails-4


【解决方案1】:

你的结构有几个问题:

  1. 您的form_for 中没有任何字段
  2. 您正在手动fields_for 定义字段(BIG no no)。

form_for

当您创建 form_for 时,Rails 使用 form object 从您的 model 中获取数据,并将其输出到 HTML 表单中。

此输出在渲染时完成,无论您使用 javascript 进行多少手动提升都不会改变:

<%= form_for @post do |f| %>
   # you need fields in here
   <%= f.submit %>
<% end %>

调试方法是检查页面的source (Right-Click &gt; View Source)。如果存在&lt;form&gt; 元素,则表示form_for 方法正在工作:

另外,请记住form_for 是一个辅助方法。它接受参数并输出 HTML 供您使用。这不是魔术。如果它“没有出现”,那么它必须有一个合乎逻辑的原因。


fields_for

第二步是您的fields_for 不会在没有任何对象填充的情况下显示。

当您手动添加新的fields_for 字段(基本上是antipattern)时,您也会遇到一个大问题。

您需要执行以下操作:

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def edit
    @post = Post.includes(:things).find(params[:id])
    @post.things.build unless @post.things.any?
  end
end

#app/views/posts/edit.html.erb
<%= form_for @post, url: posts_path, html: { multipart: true } do |f| %>

  <%= f.fields_for :things do |ff| %> #-> association name (plural)
     <%= ff.text_area :text, placeholder: "Write Something" %>
  <% end %> 

  <%= f.submit %>
<% end %>

fields_for 填充来自您传递给form_for 的父级的关联对象。因此,如果您尚未构建任何关联对象,则需要确保至少构建了一个,以便相应地填充字段。


嵌套

最后,您需要了解如何将fields 动态附加到fields_for 块。

虽然您的代码没有错误,但它非常不切实际。有大量资源可以为您指明正确的方向:

  1. RailsCasts Nested Forms
  2. Cocoon Gem(强烈推荐)
  3. NoMethodError within nested model form(我自己的帖子)

简而言之,您需要使用 Ruby/Rails 构建您需要的 fields_for 方法,并使用 ajax 将它们附加到您的表单中:

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def edit
    @post = Post.includes(:things).find params[:id]
    @post.things.build unless @post.things.any?
    respond_to do |format|
      format.js
      format.html
    end
  end
end

#app/views/posts/edit.html.erb
<%= form_for @post, authenticity_token: !request.xhr? do |f| %>
  <%= render partial: "things_fields", locals: { f: f } %>
  <% if !request.xhr? %>
    <%= button_to "Add Thing", edit_posts_path(@post), method: :get, remote: true %>
    <%= f.submit %>
  <% end %>
<% end %>

#app/views/posts/_things_fields.html.erb
<%= f.fields_for :things, child_index: Time.now.to_i do |ff| %>
  <%= ff.text_area :text, placeholder: "Write Something" %>
<% end %>

这将允许您通过JS 调用附加fields

#app/views/posts/edit.js.erb
$("<%=j render "edit" %>").data().appendTo("form#post);

这种方法的诀窍是使用child_index: Time.now.to_i(为每个新附加的字段提供唯一的id)。

--

长帖;如果您希望我专门与您一起浏览,您已经收到了我的电子邮件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    相关资源
    最近更新 更多