2014-10-08 21 views
0

我是使用jQuery的Rails和AJAX的新手。我的頁面有用戶選擇服務器的單選按鈕,根據這個選擇我的第一個下拉框'dir_list'填充了頂級目錄路徑,然後基於這個選擇第二個下拉框填充了用戶可以選擇的文件運行測試。無法讓AJAX或jQuery在rails4的動態選擇列表中工作

我有第一個使用單選按鈕的選擇框。我能夠在沒有AJAX的情況下做到這一點。 :onchange我調用了我的索引頁面中的JavaScript函數。它讀取值,執行一些if/else邏輯,然後使用JavaScript中的if/else邏輯硬編碼的正確本地呈現dir_list的局部頁面。我不能爲我的第二個選擇框做這個。它是動態的,它的價值必須通過AJAX傳遞。我一直在閱讀和嘗試幾天的例子,但我已經實現的AJAX和jQuery不起作用。我相信這些例子中有一些假設,我錯過了一些東西,因爲我對此很陌生。

我在Rails4中運行,所以我不能使用remote_function。我的application.js文件中有jQuery。

這裏是項目/ app/assets/javascripts/application.js文件:(我把所有jQuery/AJAX測試的例子代碼出來了,它回到了初始狀態)我應該可以做到這一點而不需要添加任何新寶石。

// This is a manifest file that'll be compiled into application.js, which will include all the files 
// listed below. 
// 
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. 
// 
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 
// compiled file. 
// 
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details 
// about supported directives. 
// 
//= require jquery 
//= require jquery_ujs 
//= require turbolinks 
//= require_tree . 

在這一點上,我開始使用form_tag並提交更改。它半工程,但因爲我有一個主表單url調用按鈕單擊我遇到問題。

第二個問題是如何插入文件的變量目錄路徑。我將爲這個問題打開另一個問題,並將這一問題集中在如何使用AJAX或jQuery上。我已經閱讀並嘗試了很多例子,所以有人請告訴我,我需要做的一步一步,以及我的具體案例的代碼示例文件的位置?

這是我的控制器代碼:索引加載。然後,當按下「驗證文件」按鈕並調用evaluate_media方法並加載回頁面時。 (這部分全部工作。)file_dir是我有表單提交以重新填充第二個選擇框調用的部分。

require 'media_info' 
require 'alias_generator' 
require 'rexml/document' 

class FileAliasValidatesController < ApplicationController 
def index 
    @state = 'index' 
    @file_alias_validate = FileAliasValidate.all 
    @file_exists_flag = "U" #U for Unknown or Undeterrmined. 
    @radio_button_value = 'miniprod' 
    @dir_path_choice = '/watchfolder/miniprod/hot' 

    end 

def file_dir 
    @dir_path_choice = params[:dir_list] 
    render :partial => 'list_files', :locals => {:dir_path_choice => @dir_path_choice } 
    end 

    def evaluate_media 
    @state = 'post' 
    @radio_button_value = params[:location] 

    #Determine if file chosen has been saved to database yet. 
    @stored_file = FileAliasValidate.where(:full_path => params[:filepath], :deleted_b => 0).first 

    if @stored_file.present? 
     @file_exists_flag = 'Y' 
     @file_exists_msg = 'File Alias has been saved in application.' 
    else 
     @file_exists_flag = 'N' 
     @file_exists_msg = 'File Alias has NOT been saved in application yet.' 
    end 

     #Store selected value for re-display on post. 
     @selected_filepath = params[:filepath] 
     @filepath = File.join(params[:filepath]) 

     @media_xml = ::MediaInfo.call(@filepath) #Filepath is sent in from the index html 
     @alias_xml = ::AliasGenerator.call(@media_xml) 

     @media_xml_for = "" 
     @alias_xml_for = "" 
     REXML::Document.new(@media_xml).write(@media_xml_for, 1) 
     REXML::Document.new(@alias_xml).write(@alias_xml_for, 1) 
     alias_parse_doc = "" 
     media_parse_doc = "" 
     alias_parse_doc = REXML::Document.new(@alias_xml) 
     media_parse_doc = REXML::Document.new(@media_xml) 


     #parse Alias XML Doc 
     @aliasgen_ver = REXML::XPath.each(alias_parse_doc, "/aliasGenerator vr=/text()") { |element| element }  
     @file_alias = REXML::XPath.each(alias_parse_doc, "*//alias/text()") { |element| element } 
     @file_status = REXML::XPath.each(alias_parse_doc, "*//error/text()") { |element| element } 
     @file_msg = REXML::XPath.each(alias_parse_doc, "*//error_m/text()") { |element| element } 
     @msg_dtl1 = REXML::XPath.each(alias_parse_doc, "*//closestvideoalias/text()") { |element| element } 
     @msg_dtl2 = REXML::XPath.each(alias_parse_doc, "*//closestaudioalias/text()") { |element| element } 

     #parse Video Media Info XML Doc 
     @filepathname = REXML::XPath.each(media_parse_doc, "*//Complete_name/text()") { |element| element } 
     @video_format = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Format/text()") { |element| element } 
     @video_bitrate = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Bit_rate/text()") { |element| element } 
     @video_width = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Width/text()") { |element| element } 
     @video_height = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Height/text()") { |element| element } 
     @video_aspectratio = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Display_aspect_ratio/text()") { |element| element } 
     @video_framerate = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Frame_rate/text()") { |element| element } 
     @video_scantype = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Scan_type/text()") { |element| element } 
     @video_scanorder = REXML::XPath.each(media_parse_doc, "//track[@type='Video']/Scan_order/text()") { |element| element } 

     render :action => :index 
    end 
end 

這裏是索引代碼:

<!DOCTYPE html> 
<head> 
    <meta http-equiv="Content-type" content="text/html; charset=utf-8"> 
    <title>Alias Validation -- Content Planner One Off Tool</title> 
</head> 
<h1>Alias File Validation</h1> 
<p><%= link_to "Main Menu Page", mainpages_home_path %> <%= ', ' %> <%= link_to "Alias Home Page", alias_main_pages_home_path %> </p> 
<%= form_tag file_alias_validates_evaluate_media_url do %> 
<p> 
    <fieldset> 
    <legend>File Information:</legend>  
    <div class="form_row"> 
     <label for="dir_location">Select File Location:</label> 
     <br><%= radio_button_tag 'location', 'miniprod', checked = true, :onclick => "render_dir_partial();" %> MiniProd Watch Folder 
     <%= radio_button_tag 'location', 'watch', checked = false, :onclick => "render_dir_partial();" %> Prod Watch Folder 
     <%= radio_button_tag 'location', 'archive', checked = false, :onclick => "render_dir_partial();" %> Prod Archive Folder 
     <%= radio_button_tag 'location', 'local', checked = false, :onclick => "render_dir_partial();" %> Local Test 
    </div> <br /> 
    <%= form_tag({:controller => 'file_alias_validates', :action => 'file_dir', :method => :get}, {:id => 'dir_select_tag'}) do %> 
    <div id="dir_list"> 
     <%= render :partial => 'dir_list', :locals => {:dir_choice => @radio_button_value } %> 
    </div><br /> 
    <% end %> 
    <div id="list_files"> 
     <label for="file_list">Select Test File:</label> 
     <label>Dir Selected Path Value: </label><%= @selected_dir_list %> 
     <%= render :partial => 'list_files', :locals => {:dir_path_choice => @dir_path_choice } %> 
    </div><br /> 
    <div  
    <table>   
     Select Test File: 
<!-- Production MiniProd Mounted Watchfolder (Both A3P and A4P Aspera folders in one read location.) -->   
     <% @files = Dir.glob("/watchfolder/miniprod/hot/**/*.{mpg,mov}").map %> 
     <%= select_tag 'filepath2', options_for_select(@files, @selected_filepath) %> 
    </table> 
    </div><br /> 
    </fieldset> 
    <div id="holder" style="width:100%"> 
    <% if @file_exists_flag == 'N' %> 
     <div id="leftValidate" style="float:left; width:50%"> 
     </p> 
     <p><%= button_tag "Validate File Alias", :type => "submit" %></p> 
     </div> 
     <div id="save_btn" style="float:right; width:50%"> 
     <p><%= button_tag "Save File Alias", :type => "submit" %></p> 
     </div> 
    <% elsif @file_exists_flag == 'Y' %> 
     <div id="leftValidate" style="float:left; width:50%"> 
     </p> 
     <p><%= button_tag "Validate File Alias", :type => "submit" %></p> 
     </div> 
     <div id="update_btn" style="float:right; width:50%"> 
     <p><%= button_tag "Update File Alias", :type => "submit" %></p>  
     </div> 
    <% else %> 
     <div id="leftValidate" style="float:left; width:100%"> 
     </p> 
     <p><%= button_tag "Validate File Alias", :type => "submit" %></p> 
     </div> 
    <% end %> 
    </div> 
<% end %> 
<body> 
    <% if @file_exists_flag == 'Y' %> 
     <span style="color:green;font-weight: bold; font-size:12px; "><%= @file_exists_msg %></span> 
    <% elsif @file_exists_flag == 'N' %> 
     <span style="color:red;font-weight: bold; font-size:12px; "><%= @file_exists_msg %></span> 
    <% else %> 
     <% @file_exists_msg %> 
    <% end %> 
    <fieldset> 
    <legend>Alias Validation Results:</legend> 
     <% if @state == "post" %> 
      <pre> 
      <label> Alias Generator Version: </label> <%= @aliasgen_ver %> 
        <label> Alias: </label> <%= @file_alias %> 
       <% if @file_status == ["F"] %> 
         <%= 'Validation Status: '%><span style="color:green;font-weight: bold; font-size:12px; "><%= 'Success!' %> </span> 
       <% else %> 
         <%= 'Validation Status: '%><span style="color:red;font-weight: bold; font-size:12px; "><%= 'Failed!' %> </span> 
       <%= 'Error Message: ' %> <%= @file_msg %> 
      <%= 'Closest Video Alias Match: ' %> <%= @msg_dtl1 %> 
      <%= 'Closest Audio Alias Match: ' %> <%= @msg_dtl2 %> 
       <% end %>    
       <!-- <%= @alias_xml_for %> --> 
      </pre> 
     <% end %> 
    </fieldset><br /> 
</body> 
    <fieldset> 
     <legend>Media Info File and Video Values:</legend> 
      <% if @state == "post" %> 
      <pre> 
<%= 'File and Path: ' %> <%= @filepathname %> <br /> 
       <%= '======================================================' %> 
       <%= '=    Video Specifications    =' %> 
       <%= '======================================================' %> 
        <%= 'Video Format: ' %> <%= @video_format %> 
       <%= 'Video Bit Rate: ' %> <%= @video_bitrate %> 
        <%= 'Video Width: ' %> <%= @video_width %> 
        <%= 'Video Height: ' %> <%= @video_height %> 
       <%= 'Video Frame Rate: ' %> <%= @video_framerate %> 
       <%= 'Video Aspect Ratio: ' %> <%= @video_aspectratio %> 
        <%= 'Video Scan Type: ' %> <%= @video_scantype %> 
        <%= 'Video Scan Order: ' %> <%= @video_scanorder %>   
       <!-- <%= @media_xml_for %> --> 
      </pre> 
      <% end %>  
    </fieldset><br /> 
</body>  

    <fieldset> 
     <legend>Media Info XML:</legend> 
      <% if @state == "post" %> 
      <pre> 
       <%= @media_xml_for %> 
      </pre> 
      <% end %>  
    </fieldset><br /> 

</body> 


<script> 
function render_dir_partial() { 
    alert('in javascript.'); 
    alert("you chose the option: " + $('form input[type=radio]:checked').val()); 
    radio_button_value = $('form input[type=radio]:checked').val(); 
    alert ("radio_button_value: " + radio_button_value); 
    if (radio_button_value == 'miniprod') { 
     $('#dir_list').html('<%=j render :partial => "dir_list", :locals => { :dir_choice => 'miniprod' } %>') 
    } else if (radio_button_value == 'watch') { 
     $('#dir_list').html('<%=j render :partial => "dir_list", :locals => { :dir_choice => 'watch' } %>') 
    } else if (radio_button_value == 'archive') { 
     $('#dir_list').html('<%=j render :partial => "dir_list", :locals => { :dir_choice => 'archive' } %>') 
    } else if (radio_button_value == 'local') { 
     $('#dir_list').html('<%=j render :partial => "dir_list", :locals => { :dir_choice => 'local' } %>') 
    } else { 
     $('#dir_list').html('<%=j render :partial => "dir_list", :locals => { :dir_choice => '' } %>') 
    } 
} 
</script> 

這裏是第一 'dir_list' 部分編碼:

<div> 
     <label>Select Directory Path:</label><br /> 
     <label>Dir_Choice: </label><%= dir_choice %> 
     <% if dir_choice== "miniprod" %> 
      <% @dir_list = Dir["/watchfolder/miniprod/*"] %>    
     <% elsif dir_choice== "watch" %> 
       <% @dir_list = Dir["/watchfolder/*"].reject{ |f| f[%r{^/watchfolder/miniprod}] || f[%r{^/watchfolder/aspera_console}]} %> 
     <% elsif dir_choice== "archive" %> 
       <% @dir_list = Dir["/archive/*"] %> 
     <% elsif dir_choice== 'local'%> 
       <% @dir_list = Dir["/home/silver/test/*"] %> 
     <% else %> 
      <% @dir_list = ["/watchfolder/aspera_console/"] %> 
     <% end %> 
     <%= select_tag 'dir_list', options_for_select(@dir_list, @selected_dir_list), :onchange => "this.form.submit();", :with => "'dir_list='+this.options[this.selectedIndex].value", :remote => true %> 
    </div> 

這裏是第二下拉框部分 'list_files'。 (注意:@files目錄是硬編碼的,因爲我不知道如何正確地插入@dir)。 #{@ dir}在嵌入式Ruby中不起作用。我嘗試了erb模板,然後出現錯誤「無法將nil轉換爲字符串」。

require 'erb' 
    <p>   
     <label>Select Partial Test File:</label><br /> 
     <label>Dir Partial Selected Path Choice: </label><%= dir_path_choice %><br /> 
     <%= @dir_path_choice = params[:dir_list] %> 
     <label>Partial Path Choice: </label><%= @dir_path_choice %><br /> 
     <% if @dir_path_choice %> 
      <% @dir = 'Dir.glob("' << @dir_path_choice << '/**/*.{mpg,mov}").map' %> 
     <% else %> 
     <% @dir = 'Dir.glob('"/watchfolder/miniprod/hot/**/*.{mpg,mov}"').map' %> 
     <% end %> 
     <label>Partial Dir: </label><%= @dir %><br /> 
     <% @files = Dir.glob("/watchfolder/showtimevod/**/*.{mpg,mov}").map %> 
     <%= select_tag 'filepath', options_for_select(@files, @selected_filepath) %> 
    </p> 

這裏是我的佈局application.html:
(我有jQuery的在那裏從教程之一,請讓我知道,如果我需要與否。)

<!DOCTYPE html> 
<html> 
<head> 
    <title>CpOneOffd</title> 
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 
    <%= javascript_include_tag 'jquery','application', 'data-turbolinks-track' => true %> 
    <%= csrf_meta_tags %> 
</head> 
<body> 

<%= yield %> 

</body> 
</html> 

注意:我現在有兩次文件選擇框。我將舊的硬編碼版本與<table>標籤放在一起,然後添加上面的動態部分進行測試,直到我可以使用它。請不要讓這兩個人在查看我的代碼時感到困惑。

有一個驗證文件別名按鈕。用戶選擇文件後,他們然後單擊驗證文件別名,並使用調用2庫文件調用評估媒體方法。一個運行媒體信息並獲取XML,然後將XML傳遞給自定義代碼,以確定內部別名。它現在重新加載帶有URL的網頁,用於評估媒體和顯示的所有媒體數據。

當我選擇目錄時,在更改時評估媒體顯示。它確實表明我的選定值在顯示屏幕中正確傳遞。我只是沒有動態讀取文件。 (我的第二個代碼問題)。您還會注意到我將添加一個保存按鈕並更新按鈕,以將爲該文件顯示的數據保存到表中。

UI快照:

enter image description here

回答

0

你有沒有得到任何Ajax請求的工作?如果沒有,爲什麼你會在複雜的設置中嘗試ajax請求來學習如何創建ajax請求?相反,你應該首先創建一個帶有index.html.erb頁面的控制器,該頁面簡單地顯示'Hello world',然後在頁面中添加一個按鈕,並在點擊時添加一些jQuery到發送ajax get請求的頁面當索引控制器收到一個ajax請求時,讓索引控制器以字符串「Goodbye」響應,然後讓你的jQuery alert()這個字符串,一旦你得到這個工作,然後讓jQuery替換「Hello世界「與索引動作返回的字符串,即」再見「

一旦你得到了一些簡單的工作,你可能會更好地理解jQuery和ajax請求的工作方式。 Firefox + Firebug檢查請求和響應並跟蹤任何javascript錯誤。

下一步是在index.html.erb中添加一個select,並嘗試編寫一些jQuery,onchange向ajax請求發送一個ajax請求,該ajax響應ajax請求將字符串「I收到選擇:'server1'「,然後在選擇後在頁面上插入。

至於你當前的項目:

1)此代碼:

<label for="dir_location">Select File Location:</label> 
<br><%= radio_button_tag(
     'location', 
     'miniprod', 
     checked = true,   
     :onclick => "render_dir_partial();" 
) %> MiniProd Watch Folder 

會生成HTML:

<input checked="checked" id="location_miniprod" name="location" onclick="render_dir_partial();" type="radio" value="miniprod" /> MiniProd Watch Folder 

,並把JavaScript的HTML標籤內被認爲是不好的做法。好的做法是保持javascript和html分開。你可以通過使用jQuery來選擇單選按鈕併爲它們添加onclick事件處理程序。另外:

總是使用複選框和單選按鈕的標籤。他們將文本 與特定選項相關聯,並通過擴展可點擊區域,使用戶點擊其[[選擇]更容易 。

http://guides.rubyonrails.org/form_helpers.html

例如:

<%= radio_button_tag('location', 'miniprod') %> 
<%= label_tag('location_miniprod', 'MiniProd Watch Folder') %> 

另外,如果用戶想選擇的第一個服務器是什麼?在您的代碼中,默認情況下會進行檢查,因此要獲取針對第一臺服務器的onclick事件,用戶必須單擊另一臺服務器,然後單擊第一臺服務器。在我看來,你應該保留所有的單選按鈕不被選中,這樣用戶必須點擊一個服務器來選擇它。

2)

在這一點上,我開始使用的form_tag和提交的變化。它半 工程,但因爲我有一個主窗體url調用按鈕單擊我運行 成問題。

什麼是「按鈕點擊的主表單url調用」?這是否意味着您將一個onclick事件處理程序附加到窗體標記?如果是這樣,則可以防止從冒泡直至父標籤的事件。在jQuery中,所有的事件處理函數傳遞的事件對象作爲參數,並冒泡到父元素停止的情況下,你寫的:

function(event) { 
    ... 
    event.stopPropagation; 
} 

3)所有這些行:

@aliasgen_ver = REXML::XPath.each(alias_parse_doc, "/aliasGenerator vr=/text()") { |element| element } 

可以被替換爲:

@aliasgen_ver = REXML::XPath.match(alias_parse_doc, "/aliasGenerator vr=/text()") 

你不遍歷集合,以獲得集合。你在做什麼相當於寫作:

arr = [1, 2, 3].each {|num| num } 

由於每個()返回其接收機,[1,2,3]最終被分配給編曲。但是,你可以這樣寫:

arr = [1, 2, 3] 

是的,REXML教程很爛 - 它應該告訴你的第一件事是如何得到匹配元素的數組。另外,REXML是老而慢的。 Nokogiri是人們現在使用的東西,因爲它可以做更多的事情,而且速度很快。

4)

// This is a manifest file that'll be compiled into application.js, which 
// will include all the files listed below. 
//= require jquery 
//= require jquery_ujs 
//= require turbolinks 
//= require_tree . 

換句話說,所有提到的文件會被塞進的application.js,所以如果你有一個鏈接到的application.js script標籤,你在這些文件中得到的一切,因此此行:

<%= javascript_include_tag 'jquery','application', 'data-turbolinks-track' => true %> 

指定一個文件太多以便鏈接到。

5)所有這些代碼:

<% if dir_choice== "miniprod" %> 
     <% @dir_list = Dir["/watchfolder/miniprod/*"] %>    
    <% elsif dir_choice== "watch" %> 
      <% @dir_list = Dir["/watchfolder/*"].reject{ |f| f[%r{^/watchfolder/miniprod}] || f[%r{^/watchfolder/aspera_console}]} %> 
    <% elsif dir_choice== "archive" %> 
      <% @dir_list = Dir["/archive/*"] %> 
    <% elsif dir_choice== 'local'%> 
      <% @dir_list = Dir["/home/silver/test/*"] %> 
    <% else %> 
     <% @dir_list = ["/watchfolder/aspera_console/"] %> 
    <% end %> 

...無關與生成HTML - 代碼只是設置@變量的值 - 因此它應該在的控制器。

6)

它讀值,做一些的if/else邏輯,然後呈現 部分頁面的dir_list ...

您有發生一樣。

瀏覽器不知道部分是什麼。當請求觸發索引操作時,Rails通過執行ruby代碼並填充頁面將部分html.erb文件轉換爲純html(和javascript),然後將純html頁面發送到瀏覽器。然後你的瀏覽器在適當的時候執行javascript if-else邏輯。當事情執行時,你必須把事情記在心裏。當事情變得太複雜時,比如你的代碼,你應該嘗試瀏覽你的模板,用硬編碼值代替ruby變量,看看你最終得到的html文件是否合理。這裏是你的index.html.eb文件是什麼樣子的軌道後插入部分和Rails是試圖執行Ruby代碼:

function render_dir_partial() { 
    radio_button_value = <will be fetched when this js function executes>; 

    if (radio_button_value == 'miniprod') { 
     $('#dir_list').html(---+ 
           | 
           | dir_choice = 'miniprod' 
           | 
           V 
    <div> 
     <label>Select Directory Path:</label><br /> 
     <label>Dir_Choice: </label>miniprod 
                    undefined! 
      @dir_list = ['a', 'b', 'c']        | 
                     V 
     <%= select_tag 'dir_list', options_for_select(@dir_list, @selected_dir_list), :onchange => "this.form.submit();", :with => "'dir_list='+this.options[this.selectedIndex].value", :remote => true %> 
    </div> 

此外,select_tag()不具有:遠程=>真選項,也沒有:with選項。見select_tag的文檔()位置:

http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-select_tag

而且任何選項不被select_tag承認()方法將被用於創建的HTML屬性,像這樣:

<select remote="true" with="'dir_list='+this.options[this.selectedIndex].value" > 

和這些html屬性是毫無意義的。

下面是一個可以做你正在做的事情的例子。一旦用戶從文件選擇中選擇了文件,用戶就可以點擊提交將所有數據發送到服務器(即指向表單的操作屬性中指定的任何操作)。我認爲提交變更表格不是一個好主意,因爲如果用戶偶然選擇錯誤的東西會怎麼樣?

應用程序/控制器/ file_controller.rb:

class FileController < ApplicationController 

    def index 
    if request.xhr? 
     #Use params[:server] and params[:dir] to retrieve whatever files you want 
     server = params[:server] 
     dir = params[:dir] 
     puts "***#{server}" #Will be output to server window 
     puts "***#{dir}" 

     retrieved_file_names = [ 
     "a (#{server}/#{dir})", 
     "b (#{server}/#{dir})", 
     "c (#{server}/#{dir})", 
     ] 

     render partial: 'select', locals: {file_names: retrieved_file_names} 

    else 

     @servers = %w[ miniprod watch archive local ].each 
     @radio_labels = [ 
     "MiniProd Watch Folder", 
     "Prod Watch Folder", 
     "Prod Archive Folder", 
     "Local Test", 
     ].each 

     @miniprod_dirs = ['miniprod_dir1', 'miniproddir2'] 
     @watch_dirs = ['watch_dir1', 'watch_dir2', 'watch_dir3'] 
     @archive_dirs = ['archive_dir1', 'archive_dir2', 'archive_dir3'] 
     @local_dirs = ['local_dir1', 'local_dir2', 'local_dir3'] 
    end 

    #By default, renders 'views/file/index.html.erb' 
    end 

end 

這裏是由index.html.erb產生的形式:

<form id="file_form" action="some_controller/some_action" method="post"> 

    <div> 
    <input id="location_miniprod" name="location" type="radio" value="miniprod" /> 
    <label for="location_miniprod">MiniProd Watch Folder</label> 
    </div> 

    <div> 
    <input id="location_watch" name="location" type="radio" value="watch" /> 
    <label for="location_watch">Prod Watch Folder</label> 
    </div> 

    <div> 
    <input id="location_archive" name="location" type="radio" value="archive" /> 
    <label for="location_archive">Prod Archive Folder</label> 
    </div> 

    <div> 
    <input id="location_local" name="location" type="radio" value="local" /> 
    <label for="location_local">Local Test</label> 
    </div> 


    <div id='dirs_div'></div> 
    <div id='files_div'></div> 

    <div><button type="submit">Submit</button></div> 
</form> 

index.html.erb:

<h1>File#index</h1> 
<p>Find me in app/views/file/index.html.erb</p> 

<form id="file_form" action="some_controller/some_action" method="post"> 

<% 
loop do 
    server = @servers.next 
    radio_label = @radio_labels.next 
%> 
    <div> 
    <%= 
     radio_button_tag(
     name = 'location', 
     value = server, 
     #checked = (server == 'miniprod') 
    ) 
    %> 
    <%= 
     label_tag(name="location_#{server}", content=radio_label) 
    %> 
    </div> 

<% end %> 

    <div id='dirs_div'></div> 
    <div id='files_div'></div> 

    <div><button type="submit">Submit</button></div> 
</form> 

<script> 
function create_select(server_choice) { 

    var dirs_for = { 
    miniprod: <%= raw @miniprod_dirs %>, //raw() somehow converts ruby arrays to js arrays 
    watch: <%= raw @watch_dirs %>, 
    archive: <%= raw @archive_dirs %>, 
    local: <%= raw @local_dirs %> 
    } 
    var dirs = dirs_for[server_choice]; 

    var $new_select = $('<select id="directory" name="directory">'); 
    var options = []; 

    //Create option that says 'select directory': 
    options.push(
    $("<option>", {selected: "selected", disabled: "disabled", text: "select directory"}) 
); 

    var i; 
    var len = dirs.length; 
    var dir_name; 

    for(i=0; i< len; i++) { 
    dir_name = dirs[i]; 
    options.push( 
     $("<option>", {value: dir_name, text: dir_name}) 
    ); 
    } 

    $new_select.append(options); 

    $new_select.on("change", function() { 
    var dir_choice = $(this).val() 

    //Here's the ajax request: 
    $.get(
     '/file/index', 
     {server: server_choice, dir: dir_choice}, 
     function(select_html) { $("#files_div").html(select_html) }, 
     'html' 
    ); 

    }); 

    $('#dirs_div').html($new_select); 
    //In addition, when a new server is chosen, the file select, 
    //if it is already being displayed, should be deleted. 
    $('#files_div').empty() 
} 


//Add an onclick event handler to each of the radio buttons: 
$('input[name=location]', '#file_form').on('click', function(event) { 
    var server_choice = $(this).val() 
    create_select(server_choice); 
    event.stopPropagation(); //Prevent click event from 'bubbling' up to parent tags 
}); 

</script> 

app/views/file/_select.html.erb:

<%= 
prompt = 'select file' 

select_tag( 
    name = 'file', 
    options_for_select(
    file_names.unshift(prompt), //Add prompt to the front of the Array 
    selected: prompt, 
    disabled: prompt, 
) 
) 
%>