Ajax を使用してセレクトボックスの内容を動的に書き換える処理を実際に試した手順でまとめておきます。
事前準備
先ずは必要なモデルとコントローラを作成します。
$ ./bin/rails g model publisher name:string address:text $ ./bin/rails g model Book name:string publisher:references $ ./bin/rails g controller hello index books $ ./bin/rake db:migrate
config/routes.rb
には次のパスが追加されていると思います。
Rails.application.routes.draw do get 'hello/index' get 'hello/books' ...
rails console
を使用して以下のようなデータをDBに登録して下さい。
Publisher.create(name: "O'Reilly Japan, Inc.", address: "Yotsuya") Publisher.create(name: 'Gihyo inc.', address: 'Ichigaya') Book.create(name: 'ゼロから作るDeep Learning', publisher_id: 1) Book.create(name: '入門 Python 3', publisher_id: 1) Book.create(name: 'Pythonによるデータ分析入門', publisher_id: 1) Book.create(name: '初めてのPython', publisher_id: 1) Book.create(name: '実践 機械学習システム', publisher_id: 1) Book.create(name: 'パーフェクトRuby', publisher_id: 2) Book.create(name: 'パーフェクト Ruby on Rails', publisher_id: 2) Book.create(name: 'パーフェクトJava', publisher_id: 2) Book.create(name: 'パーフェクトJavaScript', publisher_id: 2) Book.create(name: 'パーフェクトPython', publisher_id: 2)
Viewの実装
Publisher と Book モデルの項目をセレクトボックスで選択するだけのViewをapp/views/hello/index.html.haml
で作成します。
%h1 Hello#index = select_tag :publisher_id, options_from_collection_for_select(Publisher.all, :id, :name) = select_tag :book_id, options_from_collection_for_select(Book.all, :id, :name)
Rails のサーバを起動してlocalhost:3000/hello/index
にアクセスして次のように表示されることを確認して下さい。
Ajax処理の実装
app/views/hello/index.html.haml
に以下を追記してください。Publisher のセレクトボックスが変更された時に Ajax で/hello/books
に GET リクエストを実行するコードです。
:javascript $(function() { $('#publisher_id').change(function() { $.get({ url: "#{hello_books_path}", data: { publisher_id: $('#publisher_id').has('option:selected').val() } }); }); });
app/controllers/hello_controller.rb
では受け取ったpublisher_id
に紐づく Book オブジェクトを取得します。メソッドと同名の JavaScript テンプレートを作成するため render メソッドは省略しています。
class HelloController < ApplicationController def index; end def books @books = Book.where(publisher_id: params[:publisher_id]) end end
レスポンスに使用する JavaScript テンプレートapp/views/hello/books.js.erb
を用意します。処理内容としては option タグを新しく生成して丸ごと書き換えているだけです。
$('#book_id').html('<%= j(options_for_select(@books.pluck(:name, :id))) %>');
ちなみにoptions_for_select
は option タグを生成する View ヘルパーですが、index.html.haml で使用していたoptions_from_collection_for_select
とは使い方が違うだけで同じ用途になります。j( ... )
はescape_javascript( ... )
の alias です。
動作確認
実際に Publisher のセレクトボックスを変更した時に、Book のセレクトボックスが変更されていれば成功です。/hello/books?publisher_id=2
へのリクエストが実行されているのも確認できると思います。
今回は JavaScript テンプレートを使用したやり方でしたが JSON を返却して JavaScript 側で HTML を組み立てたりやり方はいくつかありそうです。