意见/命令/ 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 %>
视图/ 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
车型/ 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的行进入表单.如果你点击添加行,我得到
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>
意见/命令/ 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没有保存.我知道这很讨厌,但我不知道去哪里.
UPDATE
路线:
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,@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,{class: 'form-control'} %></td>
<td><%= d.text_field :quantity,class: 'form-control' %></td>
<td>$$$</td>
<% end %>
<% end %>
解决方法
这里有一个非常非常好的教程:http://pikender.in/2013/04/20/child-forms-using-fields_for-through-ajax-rails-way/
我们最近也在我们的开发应用程序中实现了这种形式.如果你去http://emailsystem.herokuapp.com,注册(免费),然后点击“新消息”. “订阅者”部分使用此技术
BTW我们这样做了.茧实际上看起来真的很好,似乎使用与我们一样的原则.还有一个RailsCast,但这只适用于单个添加(我想)
f.fields_for
您所做的方式是使用一系列部分动态构建所需的字段.从您的代码看,您的基础知识(表单正在运行)看起来像现在这样构建几个组件以处理AJAX请求的情况:
>您需要处理控制器上的AJAX(路由控制器动作)
>你需要把你的f.fields_for部分(所以可以用Ajax调用)
>您需要处理模型中的构建功能
使用控制器处理AJAX
首先,您需要处理控制器中的Ajax请求
为此,您需要向路由添加一个新的“端点”.这是我们的
resources :messages,:except => [:index,:destroy] do
collection do
get :add_subscriber
end
end
控制器动作然后转换为:
#app/controllers/messages_controller.rb
#Ajax Add Subscriber
def add_subscriber
@message = Message.build
render "add_subscriber",:layout => false
end
将您的f.fields_for添加到部分
为了处理这个,你需要把你的f.fields_for部分.这是我们的形式的代码形式:
#app/views/resources/_message_subscriber_fields.html.erb
<%= f.fields_for :message_subscribers,:child_index => child_index do |subscriber| %>
<%= subscriber.collection_select(:subscriber_id,Subscriber.where(:user_id => current_user.id),:name_with_email,include_blank: 'Subscribers') %>
<% end %>
#app/views/messages/add_subscriber.html.erb
<%= form_for @message,:url => messages_path,:authenticity_token => false do |f| %>
<%= render :partial => "resources/message_subscriber_fields",locals: {f: f,child_index: Time.Now.to_i} %>
<% end %>
#app/views/messages/new.html.erb
<% child_index = Time.Now.to_i %>
<div id="subscribers">
<div class="title">Subscribers</div>
<%= render :partial => "message_subscriber_fields",child_index: child_index } %>
</div>
将您的构建功能扩展到您的模型
为了保持干燥,我们在模型中创建了一个构建函数,每次我们可以调用它们:
#Build
def self.build
message = self.new
message.message_subscribers.build
message
end
Child_Index
你最好的朋友是child_index
如果你添加了多个字段,那么你会遇到的大问题是增加字段的[id](这是我们用Ryan Bates教程发现的缺陷)
我发布的第一个教程解决方法的方法是使用Time.Now.to_i设置新字段的child_index.这将设置一个唯一的ID,并且因为新字段的实际ID不相关,所以您可以添加任意数量的字段
JQuery的
#Add Subscriber
$->
$(document).on "click","#add_subscriber",(e) ->
e.preventDefault();
#Ajax
$.ajax
url: '/messages/add_subscriber'
success: (data) ->
el_to_add = $(data).html()
$('#subscribers').append(el_to_add)
error: (data) ->
alert "Sorry,There Was An Error!"