セレクトメニューの選択項目に応じて、もう1つのセレクトメニューの内容を変更する

ひとまずメモ。

覚え書き

  • Rubyの配列のinspect結果(#Array.inspect)が、javascriptの配列の表現と良く似ていることを利用する。nil表現だけ違うので、gsubで変更。
  • Railsのselectヘルパーを使うと、変更するSELECTタグのname属性に[]が入ってしまってjavascript的に許されない名前っぽいので、selectヘルパーは使わない。

View

<h1>アップロードフォーム</h1>

<%= start_form_tag({:action => 'save'},  {:multipart => true, :name => 'upload_form'}) %>
  <p>
    <b>ファイル:</b>
    <%= file_field "data_file", "file_data" %>
  </p>

  <script language="JavaScript"><!--
    menuItem = <%= @menus.inspect.gsub("nil,", "null,") %> ;

    function setMenuItem(select_obj) {
      n = select_obj.value;
      s = document.upload_form.search_key;
      max_num = menuItem[n].length;
    
      for (i = s.length - 1; i >= max_num ; i--) { s.options[i] = null; }
      for (i = 0; i < max_num; i++) { 
        s.options[i] = new Option(menuItem[n][i][0],menuItem[n][i][1]); 
      }
    }
// --></script>

  <p id="search_keys">
    <b>項目:</b>
    <%= select 'article', 'id', @articles.map{|a| [ a.name, a.id ]}, {}, { 'onChange' => 'setMenuItem(this)'} %>
    &nbsp;
    <b>検索キー:</b>
    <select name="search_key">
      <% @search_keys.each do |search_key| -%>
      <option value="<%= search_key.id %>"><%= search_key.name %></option>
      <% end -%>
    </select>
  </p>
  <%= submit_tag "Upload" %>
<%= end_form_tag %>

Controller

class UploadController < ApplicationController
  def index
    @articles = Article.find(:all)
    @article = @articles[0]

    @menus = []
    @articles.each do |a|
      @menus[a.id] = SearchKey.find(:all, :conditions => ["article_id = ?", a.id]).map{|s| [s.name, s.id]}
    end    
    @search_keys = SearchKey.find(:all, :conditions => ["article_id = ?", @article.id])
    @data_file = DataFile.new

    @search_key = @search_keys[0]
  end
end