我有一个非常简单的表单,工作良好,直到我尝试重新提交。在此之后,它更新记录而不是创建新记录:
在我看来,我有这个:
#new_order_form
= render 'form'
和我的form partial:
= semantic_form_for [@location, @order], :remote => true do |f|
-if @order.errors.any?
#notice{:class=>'alert alert-block alert-error fade in'}
%a{:class=>"close", :data=>{:dismiss=>"alert", :href=>"#"}}
x
%h3
= pluralize(@order.errors.count, "error")
- @order.errors.full_messages.each do |msg|
= msg
%br
%table{:class => 'table table-bordered', :style=> {width: '50%'}}
%tr
%td= f.text_field :product_order_id, :placeholder => "Order ID"
在create.js中:
$("#new_order_form").html("<%= escape_javascript(render("form")) %>");
这可以很好地创建订单并在存在错误时呈现错误。
问题是:如果我在没有刷新页面的情况下输入另一个订单号,它会更新先前创建的记录,而不是创建一个新记录。
查看表单代码,我可以看到提交操作被替换为更新。
我试着用下面的代码替换:
= semantic_form_for [@location, @order], :remote => true do |f|
#new_order_form
= render 'form', :f => f
在create。js
$("#new_order_form").html("<%= escape_javascript(render :partial => 'form', :locals => {:f => @order}) %>");
也不工作,并报错无效的text_field。
最好的方法是什么?由于
我不是这方面的专家,但是Adam的回答似乎是正确的。我假设你的控制器动作中有如下内容:
def create
@order = Order.new(params[:order])
if @order.save
responds_to do |format|
format.js
format.html { redirect_to 'xxx' }
end
else
responds_to do |format|
format.js
format.html { render :new }
end
end
end
如果您有上述结构,那么create.js.erb只是传递在@order之后修改的@order对象。保存调用。您可以在传递的条件中重新定义它,如下所示(检查第2行)。4):
def create
@order = Order.new(params[:order])
if @order.save
@order = Order.new
responds_to do |format|
format.js
format.html { redirect_to 'xxx' }
end
else
responds_to do |format|
format.js
format.html { render :new }
end
end
end
现在,如果@order已成功保存,则将创建并传递新订单。否则,将传递带有验证错误的旧@order。
问题是您的create.js正在读取来自创建操作的结果的@order,这是现有的@order,因此它成为一个更新。
一个修复:创建一个新的@order: @order_new = Order。新在您的'if @订单。保存"create section"。
现在告诉你的form partial使用order代替@order:
semantic_form_for [@location, order], :remote => true do |f|
更新create.js:
$("#new_order_form").html("<%= escape_javascript(render 'form', :order => @order_new) %>");
确保更新任何引用表单呈现的内容,也使用:order => @order。如:
<%= render 'form', :order => @order %>
如果@location需要是一个新实例,那么同样的规则也适用。
我使用@order_new而不是覆盖@order,以防你想在你的create.js中使用@order做一些事情
旁注(供其他观众使用): Rails 3。X渲染方法不需要局部=>和局部=>帮助器。
我不熟悉semantic_form_for
,但我认为它是常规form_for
的超集。
form_for
的工作方式是,它检查模型,看看它是否被持久化,然后做默认的事情来匹配。我个人认为,从edit
行动调用form_for
将假定update
,但它没有。对于任何非持久化模型,form_for
将假定动作为create
,对于任何持久化模型,则假定动作为update
。我相信如果你想的话,你可以重写这个,但我自己还没有试过。
听起来你可能正在做的是显示模型并试图在同一页面上创建新模型。(如果我错了,请包括你的控制器,因为很难说你打算做什么。)你可能需要一个@show_order
和一个@new_order
在你的控制器。
我希望这对你有帮助,如果没有,也许你可以提供更多关于你的控制器的细节。
编辑:每当您想要能够创建一个新模型时,您需要确保您的控制器调用@new_order = Order.new
,并确保form_for
与@new_order
一起调用。new_
只是一个前缀,用来区分新旧。
在这种情况下,我不确定控制器是order#show
还是order#create
的成功部分。
对于show
,您需要这样做:
@order = Order.find(params[:id])
@new_order = Order.new
如果你在create
之外这样做,你可能需要:
@order = Order.new(params[:order])
if @order.save
@new_order = Order.new
redirect_to ???
else
render :new
end
除@new_order
外,上述所有内容都应与库存控制器完全匹配。(换句话说,不要删除respond_to
和format
行,如果他们在那里。)