当实例确实存在时,需要方法创建而不是更新

Ruby 2.0.0,Rails 4.0.3

我有一个_new部分。 但是,我用实际存在的实例渲染它。 这是必要的,这样我就可以在View和Controller之间通过JavaScript传递实例ID,因为我实际上无法传递实例本身。 我只是在新方法中调用Class.first,以便我有一个现有的实例可以在整个过程中使用。

我的问题是_new部分提交按钮识别该实例已存在。 这会导致它更新而不是创建。 该按钮字面上说更新。 按下时,它将路由到更新方法。 那不是我想要的。 我想要create方法,在那里我将创建一个填充了收集参数的新实例。

该怎么办? 我是否错误地携带一个虚拟实例来启动该过程? 如果是这样,什么是正确的解决方案? 如果这是可以接受的,我如何强制按钮创建而不是更新?

所有的帮助和评论表示赞赏

编辑:我已尝试按钮上的变化,试图强制它触发新方法。 它继续着火更新。 我最后一次失败的努力是:

 

…结束编辑…

表格是:

 

部分:

               

控制器汽车方法新的地方清除所有领域:

  def new @car = Car.first @car.clear end 

呈现forms: 在此处输入图像描述

表单的JavaScript是:

 // when the #year field changes $("#car_ymm_year_id").change(function () { // make a GET call and replace the content // First select identifies what has been selected, or fired var year = $('select#car_ymm_year_id :selected').val(); // Pull the variables from the input_html tag var form = $('select#car_ymm_year_id').attr("form"); var car_id = $('select#car_ymm_year_id').attr("car_id"); // Routes to the controller action $.post('/admin/cars/make_list/', { form: form, year: year, car_id: car_id }, function (data) { $("#car_ymm_make_id").html(data); }); return false; }); 

控制器方法:

  def make_list makes = YmmMake.makes(params[:year]) #@car = Car.find(params[:car_id]) render partial: "makes", locals: {car_id: params[:car_id], form: params[:form], makes: makes} end 

如果我理解正确,您希望实现以下目标:

显示用于创建新车型的表单。 在这种forms下,用户输入一年; 然后系统从服务器加载该年份的所有品牌,并提供一个选择下拉列表,供用户选择品牌。

Car模型belongs_to ymm_make,因此我们在提交表单时包含选定的ymm_make_id。

以下是我将如何解决这个问题。 我将使用标准的Rails表单助手,这样我们就可以减少一个抽象层了。

表格(与Car.new ):

 <%= form_for [:admin, Car.new] do |f| %> <%= f.text_field :stock_number, autocomplete: "off", placeholder: "Stock number?" %> <%= text_field_tag :year_search, nil, placeholder: "Year" %> <%= f.select :ymm_make_id %>  <%= f.submit "Create" %> <% end %> 

对于年份搜索字段,我使用text_field_tag而不是f.text_field ,因为我不希望在提交整个表单时将搜索字段值作为汽车的一部分提交。 我暂时将下拉字段留空 – 我们将通过Javascript和JSON填充它。

对于make列表,我将创建一个返回JSON的资源控制器:

 class YmmMakesController < ApplicationController respond_to :json def index @makes = YmmMake.makes(params[:year]) respond_with @makes end end 

不要忘记此控制器的route.rb条目,例如

 namespace :admin do resources :ymm_makes, only: :index end 

我们将在Javascript中使用JSON中的选项:

 $("input[name=year_search]").change(function () { // send a GET request to /admin/ymm_makes with the 'year' parameter // set to the value of the year_search text field $.getJSON( "/admin/ymm_makes", {year: $(this).val()}, function(data) { var options_html = []; // iterate over the JSON that we received back; each entry is one 'ymm_make' // in JSON form $.each( data, function( index, make ) { // make a new " ); }); // put all our generated  tags into the  

有了这一切,您应该有一个工作表单来创建与YmmMake模型对象相关联的新车。

关于您现有代码的一些观察:

嵌套表格

 <%= simple_form_for [:admin, @car] do |f| %> <%= render partial: "makes", locals: {form: 'new_admin_car', car_id: car_id} %> <% end %> 

如果我看到这个,你的'make'部分也包含一个表单,所以你创建一个嵌套在

中的

。 HTML 不允许这样做 。

错误的结束标签订单

  

<% end %>

结束必须在<% end %> 。 如果您构建无效的HTML,则可能会出现奇怪的视觉行为和Javascript错误。

冗余的论点

 <%= simple_form_for [:admin, @car], html: {id: 'new_admin_car', class: 'form-vertical', method: post}, do |f| %> 

“id”和“method”应该是默认值。 离开它们使代码更容易阅读。

通过input_html无效的属性

 <%= f.input(:stock_number, {input_html: {form: 'new_admin_car', car: @car, value: nil}, autocomplete: :off, placeholder: 'Stock number?'}) %> 

我不熟悉simple_form,但从我看到的, input_html用于向input元素添加属性。 如上所述的行将因此产生具有无效car属性的文本输入。 删除嵌套表单后,不再需要form属性。

错误的HTTP方法

 $.post('/admin/cars/make_list/' 

您通过POST AJAX请求加载您的make。 对于仅返回数据但不更改任何内容的请求,GET通常更合适。

在表单中,您可以指定提交按钮应该转到的路径:

 <%= simple_form_for [:admin, @car], url: create_action_path ... 

我认为您的答案相当简单, create而不是update ,只需清除模型的id
示例: @car.id = nil