我有一个非常简单的表单,在我尝试重新提交之前一切正常。之后,它会更新记录而不是创建新记录:
在我看来,我有这个:
#new_order_form
= render 'form'
我的形式偏:
= 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无效。
最好的方法是什么?感谢
答案 0 :(得分:1)
我不熟悉semantic_form_for
,但我认为它是常规form_for
的超集。
form_for
的工作方式是检查模型是否持久化,然后将默认值与之匹配。我个人认为从form_for
操作中调用edit
会假设为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
行。)
答案 1 :(得分:1)
问题是你的create.js正在读取来自创建操作结果的@order,这是现有的@order,因此它变成了更新。
一个修复:在'if @ order.save'创建部分中创建一个新的@order:@ order_new = Order.new。
现在告诉你的表单部分使用order而不是@order with:
semantic_form_for [@location, order], :remote => true do |f|
使用以下命令更新您的create.js:
$("#new_order_form").html("<%= escape_javascript(render 'form', :order => @order_new) %>");
确保更新引用表单呈现的任何内容以使用:order =&gt; @订购。例如:
<%= render 'form', :order => @order %>
如果你的@location需要是一个新实例,那么同样的规则也适用。
我使用@order_new而不是覆盖@order,以防你想在create.js中使用@order做一些事情
旁注(对于其他观看者): Rails 3.x渲染方法不需要partials =&gt;和locals =&gt;助手。
答案 2 :(得分:1)
我不是这方面的专家,但亚当的回答似乎是正确的。我假设您在控制器操作中有类似下面的内容:
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.save调用后修改过的@order对象。您可以在传递的条件中重新定义它,如下所示(检查第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。希望这会有所帮助。