1

我有一个名为 Pair 的模型,它有多个:问题,每个问题都有一个:答案。

我一直在关注这个关于创建嵌套表单的 railscast,但是我想在单击“添加问题”链接时同时生成一个问题字段和它的答案字段。

在遵循 railscast 之后,这就是我所拥有的:

..javascripts/common.js.coffee:

window.remove_fields = (link)->
  $(link).closest(".question_remove").remove()

window.add_fields = (link, association, content)->
  new_id = new Date().getTime()
  regexp = new RegExp("new_" + association, "g")
  $(link).before(content.replace(regexp, new_id))

application_helper.rb:

def link_to_add_fields(name, f, association)
   new_object = f.object.class.reflect_on_association(association).klass.new
   fields = f.simple_fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
     render(association.to_s.singularize + "_fields", :f => builder)
   end
   link_to_function(name, "window.add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")", class: "btn btn-inverse")
end

意见/对/_form.html.erb:

<%= simple_form_for(@pair) do |f| %>
  <div class="row">
    <div class="well span4">
      <%= f.input :sys_heading, label: "System Heading", placeholder: "required", input_html: { class: "span4" } %>
      <%= f.input :heading, label: "User Heading", input_html: { class: "span4" } %>
      <%= f.input :instructions, as: :text, input_html: { class: "span4 input_text" } %>
    </div>
  </div>

  <%= f.simple_fields_for :questions do |builder| %>
    <%= render 'question_fields', f: builder %>
  <% end %>
  <%= link_to_add_fields "<i class='icon-plus icon-white'></i> Add Another Question".html_safe, f, :questions %>
  <%= f.button :submit, "Save Pair", class: "btn btn-success" %>
<% end %>

_question_fields.html.erb 部分:

<div class="question_remove">
  <div class="row">
    <div class="well span4">
      <%= f.input :text, label: "Question", input_html: { class: "span4" }, placeholder: "your question...?" %>

      <%= f.simple_fields_for :answer do |builder| %>
        <%= render 'answer_fields', f: builder %>
      <% end %>
    </div>
  </div>
</div>

_answer_fields.html.erb 部分:

<%= f.input :text, label: "Answer", input_html: { class: "span4" }, placeholder: "your answer" %>
<%= link_to_function "remove", "remove_fields(this)", class: "float-right" %>

我对 reflect_on_association 部分特别困惑,例如调用.new那里如何创建关联?我通常需要使用.build

同样对于我使用的 has_one.build_answer而不是answers.build- 那么这对 jQuery 部分意味着什么?

4

2 回答 2

1

检查这一点的一种方法是在 Rails 控制台中运行帮助脚本。

new_object = f.object.class.reflect_on_association(association).klass.new

您正在获取 Form 对象并找到它所在的类(f.object.class - 在本例中为pair),然后使用 reflect_on_association(association) - 返回命名关联的 AssociationReflection 对象(作为符号从论据,即:问题)。

您可以使用 reflect_on_all_associations 查看每个类的所有这些 AssociationReflection 对象。

在此之后,您需要 AssociationReflection 所代表的类(这就是您使用 klass 而不是类的原因) - 然后您创建该类的新实例。

为什么不使用 build_#{association_name} 或 #{association_name}.builds 而不是 new 可能是因为脚本不知道关联是 has_one 还是 HABTM,直到它已经检索到关联对象的实例并且额外的逻辑是不值得的。

http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html

顺便说一句,修改后的 railcast 使用了一种稍微不同的方式来生成关联对象:但想法是一样的(在这种情况下,您发送 - 调用 - 表单对象上的一个方法,然后生成相关类)

new_object = f.object.send(association).klass.new

至于在帮助程序中使用两个模型沿着这条线?

application_helper.rb

def link_to_add_nested_fields(name, f, association, nested_association)
   new_object = f.object.class.reflect_on_association(association).klass.new
   new_object.send(nested_association).new
   fields = f.simple_fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
     render(association.to_s.singularize + "_fields", :f => builder)
   end
   link_to_function(name, "window.add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")", class: "btn btn-inverse")
end

例如

<%= link_to_add_fields "<i class='icon-plus icon-white'></i> Add Another Question".html_safe, f, :questions, :answer %>
于 2012-06-07T16:18:46.433 回答
0

下面的作品。我没有使用form_for代替simple_form_forfields_for代替simple_fields_for。感谢粘贴

def link_to_add_nested_fields(名称,f,关联,nested_association)

new_object = f.object.class.reflect_on_association(association).klass.new

id = new_object.object_id # 需要索引,很重要。在浏览器中检查

nested_new_object = new_object.class.reflect_on_association(nested_association).klass.new

fields = f.fields_for(association, new_object, :child_index => id) 做 |builder|

builder.fields_for(nested_association, nested_new_object, :child_index => id) do |builder1|
  render(association.to_s.singularize + "_fields", association.to_s.singularize.to_sym => builder) + render(nested_association.to_s.singularize + "_fields", nested_association.to_s.singularize.to_sym => builder1)
end

结尾

link_to(name, 'javascript:void(0)', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})

结尾

于 2020-01-09T12:27:48.783 回答