无法让AJAX或jQuery在rails4中处理动态选择列表

时间:2014-10-08 17:10:12

标签: jquery ajax ruby-on-rails-4 dynamic html-select

我是使用jQuery的Rails和AJAX的新手。我的页面有单选按钮,用户选择服务器,根据此选择我的第一个下拉框'dir_list'填充顶级目录路径,然后根据此选择,第二个下拉框填充用户可以选择的文件在。上进行测试。

我有第一个使用单选按钮的选择框。没有AJAX我就能做到这一点。 :onchange我调用索引页面中的JavaScript函数。它读取值,执行一些if / else逻辑,然后使用正确的本地呈现dir_list的部分页面,该本地是从JavaScript中的if / else逻辑进行硬编码的。我不能为我的第二个选择框执行此操作。它是动态的,值必须通过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让您对我的代码感到困惑。

有一个验证文件别名按钮。用户选择文件后,然后单击验证文件别名,并使用调用2库文件调用评估媒体方法。一个运行媒体信息并获取XML然后将XML传递给确定和内部别名的自定义代码。它现在重新加载带有URL的页面,用于evaluate_media和显示的所有媒体数据。

当我选择目录时,在更改时,评估媒体会显示出来。它确实显示我选择的值在显示屏幕中正确传递。我还没有动态读取文件。 (我的第二个代码问题)。您还会注意到我将添加一个保存按钮和更新按钮,以将文件显示的数据保存到表格中。

UI快照:

enter image description here

1 个答案:

答案 0 :(得分:0)

你有没有得到任何ajax请求工作?如果没有,为什么你会在复杂的环境中尝试ajax请求来学习如何发出ajax请求?相反,您应该首先创建一个带有index.html.erb页面的控制器,该页面只显示&#39; Hello world&#34;。然后向页面添加一个按钮,并在单击按钮时向发送ajax get请求的页面添加一些jQuery。当索引控制器if request.xhr?收到ajax请求时,使索引控制器响应字符串&#34; Goodbye&#34;。然后让你的jQuery alert()成为字符串。一旦你开始工作,那就让jQuery取代&#34; Hello world&#34;使用索引操作返回的字符串,即&#34; Goodbye&#34;。

一旦你得到类似的简单工作,你就可以更好地理解jQuery和ajax请求是如何工作的。你还应该使用像Firefox + Firebug这样的东西来检查请求和响应并跟踪任何javascript错误。

下一步是将一个select放在index.html.erb中,并尝试编写一些jQuery,onchange将一个ajax请求发送到index.html.erb,该请求响应ajax请求发送回String& #34;我收到了选择:&#39; server1&#39;&#34;,然后在选择后将其插入页面。

至于你目前的项目:

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调用按钮单击我运行   问题。

什么是&#34;主要表单网址调用按钮点击&#34;?这是否意味着您将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 }

因为each()返回其接收器,[1,2,3]最终被分配给arr。但你可以写:

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的脚本标签,你就可以获得这些文件中的所有内容,因此这一行:

<%= 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文件是否有意义。以下是在rails插入部分和rails之后你的index.html.eb文件试图执行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()没有:remote =&gt; true选项,也没有: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属性毫无意义。

下面是一个示例,它可以帮助您完成所需的操作。一旦用户从文件选择中选择文件,用户就可以点击提交以将所有数据发送到服务器(即,在表单的动作属性中指定的任何动作)。我不认为提交表格onchange是一个好主意,因为如果用户偶然选择了错误的东西怎么办?

应用程序/控制器/ 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>

应用程序/视图/文件/ _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,
  )
) 
%>