【发布时间】:2013-12-24 13:11:30
【问题描述】:
我很好奇如何正确使用accepts_nested_attributes_for和f.fields_for。
views/orders/new.html.erb
<%= form_for @order, html:{role: "form"} do |f| %>
<%= f.submit "Don't push...", remote: true %>
<%= f.text_field :invoice %>
<%= f.text_field :ordered_on %>
<%= f.text_field :delivered_on %>
<table id='order_form'>
<h3>Details</h3>
<tbody>
<%= render 'order_details/details', f: f %>
</tbody>
<%= link_to 'add line', new_order_detail_path(company_id: params[:company_id]), remote: true %>
<%= link_to 'new box', new_box_path, remote: true %>
</table>
<% end %>
views/order_details/_details.html.erb
<tr class='row0'>
<%= f.fields_for :order_details, child_index: child_index do |d| %>
<td><%= d.collection_select :box_id, @boxes, :id, :uid, {},
{ name: "box_id", class: 'form-control'} %></td>
<td><%= d.text_field :quantity, class: 'form-control' %></td>
<td><%= d.text_field :box_price, class: 'form-control' %></td>
<td><%= d.text_field :cb_price, class: 'form-control' %></td>
<td><%= d.text_field :mould_fees, class: 'form-control' %></td>
<td>$$$</td>
<% end %>
</tr>
<tr class='box0'>
<td colspan="6">→ <b><%= @b.uid %></b> | length: <%= @b.length %> | width: <%= @b.width %> | height: <%= @b.height %> | weight: <%= @b.weight %></td>
</tr>
controllers/orders_controller.rb(我很确定这是错误的......这里的任何帮助将不胜感激)
def create
@order = Order.create(params[:order])
if @order.save
flash[:success] = "Order #{@order.invoice} added!"
redirect_to current_user
else
render 'orders/new'
end
end
models/order.rb
class Order < ActiveRecord::Base
attr_accessible ..., :order_details_attributes
has_many :order_details
accepts_nested_attributes_for :order_details
end
我能够让局部发挥得很好的唯一方法是如果我实际上将fields_for 称为fields_for Order.new.order_details.build。但这根本不会构建嵌套对象。我需要使用f.fields_for 命名法来构建Order 和OrderDetail。不过,我只能建造一个。这是我的下一个问题。
看看里面怎么有按钮?它将 AJAX 行插入表单。如果你点击add line,我会得到
NameError in Order_details#new
Showing D:/Dropbox/Apps/rails_projects/erbv2/app/views/order_details/new.js.erb where line #3 raised:
undefined local variable or method `f' for #<#<Class:0x5cf0a18>:0x5cbd718>
views/orders/add_detail.js.erb
$('#order_form tr.total').before("<%= j render partial: 'orders/details', locals: {f: @f, child_index: @ci} %>")
我不知道如何定义f...我查看了Rails AJAX: My partial needs a FormBuilder instance 和其他几个。
关于我应该如何处理这个问题有什么建议吗?使用我在这里的代码...我能够创建一个新订单,并带有关联的 order_details,但 box_id 没有保存,company_id 没有保存。我知道这有点讨厌,但我不知道还能去哪里。
更新
路线:
resources :orders do
collection { get :add_detail }
end
this is way better than having a separate resource for the details. I didn't think of this before!
HTML 表单:
<%= form_for @order, company_id: params[:company_id], html:{role: "form"} do |f| %>
f. ...
<%= render partial: 'details', locals: { f: f } %> #first child
<%= link_to 'add line', add_detail_orders_path(company_id: params[:company_id]), remote: true %> #add subsequent children
<% end %>
订单控制器:
def add_detail
@order = Order.build
@boxes = Company.find(params[:company_id]).boxes
@b = @boxes.first
@ci = Time.now.to_i
respond_with(@order, @boxes, @b, @ci)
end
_details 部分
<%= form_for @order do |f| %>
<%= f.fields_for :order_details, child_index: @ci do |d| %>
<td><%= d.collection_select :box_id, @boxes, :id, :uid, {},
{class: 'form-control'} %></td>
<td><%= d.text_field :quantity, class: 'form-control' %></td>
<td><%= d.text_field :box_price, class: 'form-control' %></td>
<td><%= d.text_field :cb_price, class: 'form-control' %></td>
<td><%= d.text_field :mould_fees, class: 'form-control' %></td>
<td>$$$</td>
<% end %>
<% end %>
【问题讨论】:
-
我不完全清楚出了什么问题,但如果可能的话,您可能想查看 Cocoon gem:github.com/nathanvda/cocoon 如果您可以更清楚地知道错误发生的地点和时间,它可以帮助澄清。有很多代码可以筛选=)
-
Cocoon 看起来不错,但我不太确定它对我有什么作用。不过,第一个问题...将我的
_details partialAJAXing 到表单中失败。 (我链接到的站点中有损坏的代码,允许部分进入,但在提交表单时不会创建任何内容)。使用f.fields_for给我<select id="order_order_details_attributes_0_box_id" name="order[order_details_attributes][0][box_id]"> ... </select>,如果有2,下一个应该是1,然后是2,等等。我有意义吗?哈哈。我整天都在为此绞尽脑汁,我一直在坚持,哈哈! -
请在您的控制器中向我提供新操作,您是否在新操作中编写了构建以获取订单详细信息,例如@order.order_details.build
-
控制器中只有你看到的东西。我应该打什么电话?
标签: jquery ruby-on-rails ruby ajax ruby-on-rails-3