2014-09-10 52 views
0

Ruby 2.0.0,Rails 4.0.3需要方法創建並且在實例確實存在時不更新

我有一個_new部分。但是,我用一個實際存在的實例來渲染它。這是必要的,以便我可以通過View和Controller之間的JavaScript傳遞實例ID,因爲我實際上不能傳遞實例本身。我只需在新方法中調用Class.first,以便通過該過程使用現有實例。

我的問題是_new部分提交按鈕識別出該實例已經存在。這導致它更新而不是創建。按鈕字面上說更新。按下時,它將路由到更新方法。這不是我想要的。我想要創建方法,在那裏我將創建一個填充了收集參數的新實例。

怎麼辦?我是否僅僅攜帶一個虛擬實例來啓動流程?如果是這樣,什麼是正確的解決方案?如果這是可接受的,我該如何強制按鈕創建而不是更新?

讚賞所有的幫助和意見。

編輯:我試過按鈕上的變體,試圖強制它觸發到新的方法。它繼續着火更新。我最後的失敗努力是:

<button type="submit" formaction="new_admin_car_path" class="btn btn-default btn btn-primary">Create Car</button> 

...編輯完...

形式爲:

<div class="span8"> 
    <% car_id = @car.id %> 
    <%= simple_form_for [:admin, @car], 
         defaults: {label: false}, 
         html: {id: 'new_admin_car', class: 'form-vertical', method: post}, 
         wrapper: :vertical_form, 
         wrapper_mappings: { 
           check_boxes: :vertical_radio_and_checkboxes, 
           radio_buttons: :vertical_radio_and_checkboxes, 
           file: :vertical_file_input, 
           boolean: :vertical_boolean 
         } do |f| %> 
     <%= f.input(:stock_number, {input_html: {form: 'new_admin_car', car: @car, value: nil}, autocomplete: :off, placeholder: 'Stock number?'}) %> 
     <%= f.input(:ymm_year_id, {input_html: {form: 'new_admin_car', car_id: car_id, value: nil}, collection: YmmYear.all.order("year desc").collect{|c| [c.year, c.id]}, prompt: "Year?"}) %> 
     <%= render partial: "makes", locals: {form: 'new_admin_car', car_id: car_id} %> 
     <%= render partial: "models", locals: {form: 'new_admin_car', car_id: car_id} %> 
     <%= f.association(:color, {input_html: {form: 'new_admin_car', value: nil}, autocomplete: :off, prompt: 'Color?'}) %> 
     <div class="col-xs-6 col-sm-3"> 
     <br/> 
     <input type="submit" form="new_admin_car" value="Create Car" class="btn btn-default btn btn-primary"> 
    <% end %> 
    </div> 
</div> 

使部分:

<% unless car_id.blank? %> 
    <% car = Car.find(car_id) %> 
    <%# car.ymm_make_id = nil %> 
    <%= simple_form_for [:admin, car], 
         defaults: {label: false}, 
         remote: true do |f| %> 
     <% makes ||= "" %> 
     <% make = "" %> 
     <% make = car.make_id if car.class == Car and Car.exists?(car.id) %> 
     <% if !makes.blank? %> 
      <%= f.input :ymm_make_id, {input_html: {form: form, car: car, car_id: car.id, value: make}, collection: makes.collect { |s| [s.make, s.id] }, prompt: "Make?"} %> 
     <% else %> 
      <%= f.input :ymm_make_id, {input_html: {form: form, car: car, car_id: car.id, value: make}, collection: [], prompt: "Make?"} %> 
     <% end %> 
    <% end %> 
<% end %> 

控制器租車方法新的地方清除所有領域:

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

呈現的表單: enter image description here

的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 
+0

您能否通過在視圖和控制器之間通過JavaScript傳遞實例ID來詳細說明您的意思嗎?我們可能能夠在那裏找到更好的解決方案,並首先避免整個事情。使用現有的實例,然後強制表單助手將其視爲一個帶有撬棒的新實例,這聽起來確實是一個糟糕的主意。 – janfoeh 2014-09-13 13:55:47

+0

@janfoeh我試圖保持簡單,但這不工作,所以...我已經更新了問題,包括所有相關的部分,形式和方法。問題是我有一系列依賴選擇。當我爲汽車選擇一年的時候,它將返回所有「製造」或那年製造汽車的製造商。等等......爲此,我使用一個實例。請參閱代碼並讓我知道你是否還有其他問題。謝謝。 – 2014-09-13 14:32:56

+0

我認爲你的代碼有一些誤解和徹底的錯誤。我會創建一個空白的,乾淨的版本,試圖實現你的目標,並嘗試清除這些內容。 – janfoeh 2014-09-13 15:44:32

回答

1

如果我理解正確此,要實現以下目標:

顯示用於創建新車型的形式。在這種形式下,用戶輸入一年;然後系統從服務器加載當年的所有品牌,並提供一個選擇下拉菜單供用戶選擇一個品牌。

汽車模型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 %> 

    <!-- skipping models and colors here for the sake of brevity --> 

    <%= f.submit "Create" %> 
<% end %> 

今年首搜索領域,我用text_field_tag代替f.text_field,因爲我不想讓搜索字段值提交作爲汽車的一部分做當整個表格被提交時。現在我將下拉字段留空 - 我們將通過Javascript和JSON填充該字段。

對於品牌的名單,我會返回一個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 

我們會讓<select>選擇我們的JSON在Javascript:

$("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 <option> tag for each make and push it into the options_html array 
     // I assume here that YmmMake has an attribute called 'name' you want to display 
     options_html.push("<option value='" + make.id + "'>" + make.name + "</option>"); 
     }); 

     // put all our generated <options> tags into the <select> tag 
     $('select#car_ymm_make_id').html(options_html.join('')); 
    }); 

}); 

有了這一切之後,就應該有創建與一個YmmMake模型相關聯的新車工作形式目的。

你的現有代碼的一些意見:

嵌套形式

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

如果我看到這個正確的,你的「使」部分還包含一個表單,所以您要創建一個<form>嵌套在<form>。 HTML does not allow that

錯誤關閉標籤順序

 <div class="col-xs-6 col-sm-3"> 
     <br/> 
     <input type="submit" form="new_admin_car" value="Create Car" class="btn btn-default btn btn-primary"> 
    <% end %> 
    </div> 

收盤</div>必須出現在<% end %>之前。如果您構建了無效的HTML,則會冒着奇怪的視覺行爲和Javascript錯誤。

冗餘參數

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

「id」 和 「方法」 應該是默認值。將它們排除在外將使代碼更易於閱讀。

無效<input>屬性通過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用於屬性添加到輸入元素。像上面這樣的行會因此產生一個帶有無效car屬性的文本輸入。刪除嵌套表單後,應該不再需要form屬性。

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

您通過POST AJAX請求加載您的品牌錯誤的HTTP方法。對於只返回數據但不改變任何內容的請求,GET通常更合適。

+0

好吧,看起來很有趣,我正在努力實現它。但是,我的應用程序基於簡單表單。建議在其中實施這個? – 2014-09-14 15:56:54

+0

我建議先從內置的表單助手開始,如上所述。只要你有一個工作基線,你可以重構它以使用簡單表單,直到它再次工作。這兩種方法不是相互排斥的,可以並行使用。 – janfoeh 2014-09-14 18:18:27

+0

實施這個建議有幾個問題,但最終它比舊的代碼有了很大的改進。謝謝。 – 2014-09-18 09:53:42

0

在你的表格,您可以指定路徑提交按鈕應該去到:

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

... 
+0

沒有改變任何東西。謝謝。 – 2014-09-13 13:44:08

0

我認爲你的回答很簡單,到create而不是update,只要清除模型的id即可。
示例:@car.id = nil

相關問題