Webアプリケーションには検索機能がつきものだと思いますが、場合によっては作るのがちょっと面倒なときがあります。例えば、1対多の親子関係を持つモデルで、子供のレコードを検索する場合に、親を特定した上で検索を行う場合などです。ちょっと具体例で考えてみましょう。
Customer(顧客)とSale(売上)の2つのモデルがあるとします。2つのモデルは1対多の関連があり、Customerが複数のSaleを所有しています。この状況下におけるのSaleの検索画面を考えてみます。
検索条件として、『Customer(顧客)』『Buy on(購入日)』『Product(商品名)』の3つを用意してみました。ここで注目してほしいのはCustomerです。SaleはCustomerに紐付いているので、例えば「Johnnyさんの売上一覧が見たい」という場合には、Customerセレクトボックスから”Johnny”を選択してもらうことになります。
Customerが少ない場合はこれでよいかもしれません。しかし、Customerが大量に登録されている場合はどうでしょうか? おそらく想像に易いことだと思いますが・・・
恐怖のセレクトボックスができてしまいました! 顧客が1,000人だとすると、1,000行ものリストになるということです。この中からマウスとカーソルキーだけで1つを選べというのでしょうか? それはユーザーに対し、あまりにも酷な仕打ちです。
対処方法として、Customerに対する検索条件を分割することが考えられます。例えば、『first_name』『last_name』『tel』『email』を検索条件にしてしまうのです。
確かに1,000行から1つを選択するという状況は回避することができましたが、Saleの検索画面にCustomerの検索条件が多すぎるのも本末転倒です。また、検索条件として使用した項目を検索結果一覧に表示していないのもよろしくありません。かといって、全部表示するとSale一覧というより、Customer一覧画面になってしまうし・・・。
最も深刻なのは、上の画面だとCustomerIdを選択させているわけではないので、「とある顧客(customer_id)に紐付く売上一覧が見たい」という要求に応えられていないということです。
というわけで、chosenを使用する
chosenとは様々な機能を持ったセレクトボックスを生成するためのjQueryプラグインです。このchosenをrailsで手軽に利用するためのgemがあるので、そちらを使用します。
環境
- rails 4.0.1
- chosen-rails 1.0.1
chosen-railsをインストールするために、Gemfileに以下の2行を追加します。
📄Gemfile
gem 'compass-rails', '~> 2.0.alpha.0' gem 'chosen-rails'
修正したら、bundleコマンドでインストールを完了させます。
続いて、app/assets/javascripts/application.jsを編集します。
📄appliction.js
//= require jquery //= require jquery_ujs //= require chosen-jquery //= require turbolinks //= require_tree .
3行目を追加しました。
さらに、app/assets/stylesheets/application.cssも編集します。
📄application.css
*= require_self *= require chosen *= require_tree .
2行目を追加しています。セットアップはこれで完了です。
chosenセレクトボックスを作成する
ではさっそく、あの恐怖のセレクトボックスを変更してchosenセレクトボックスを適用させましょう。まずは既存のソースコードを見ておきます。
📄index.html.erb
... <%= form_tag sales_path, method: :get do %> <%= select_tag :customer, options_for_select( Customer.all.map {|c| [ "#{c.first_name} #{c.last_name}", c.id ] }), prompt: "(Choose a customer)" %> <%= text_field_tag :buy_on, nil, placeholder: "Buy on" %> <%= text_field_tag :product, nil, placeholder: "Product" %> <%= submit_tag "検索" %> <% end %> ...
3〜6行目のselect_tagでセレクトボックスを作成しています。これを少し修正します。
📄index.html.erb
... <%= select_tag :customer, options_for_select( Customer.all.map {|c| [ "#{c.first_name} #{c.last_name}", c.id ] }), class: "chosen-select" %> ...
修正といっても、promptを削除してclass指定を追加しただけですが。とりあえずView側はこれで準備完了しました。
さて、それではchosenセレクトボックスを適用させるためのjavascriptを記述しましょう。app/assets/javascripts/sales.js.coffeeを編集します。
📄sales.js.coffee
jQuery -> $(".chosen-select").chosen()
クラスセレクタで先程のセレクトボックスをchosen化しています。準備は全て整いました。
先程の検索画面をリロードして、出来具合を確認してみると・・・
な、なんと! あの忌まわしいセレクトボックスが、インクリメンタルサーチ付きのオシャレ系セレクトボックスになっている!! これならCustomerデータが多くても1件を選んでもらうことができそうです!
どうせなら、もう少し表示する内容を増やしてみましょう。より顧客を特定するのが簡単になるはずです。
📄index.html.erb
... <%= select_tag :customer, options_for_select( Customer.all.map {|c| [ "#{c.first_name} #{c.last_name} / #{c.tel} / #{c.email}", c.id ] }), class: "chosen-select" %> ...
調子に乗って、telやemailも表示することにしました。(本当はこんなとこにゴチャゴチャ書くべきではないですが・・・)
完成した画面をもう一度見てみます。
これで顧客を探せないなんて、もう言わせない。
比較的簡単な検索条件で事足りるモデルに対し、このchosenセレクトボックスは効果的に機能します。chosenはこの他にも、グルーピングやマルチセレクトの機能なども提供しています。サンプルも豊富なので、是非公式ページに足を運んでみてください。覚えておいて損はないプラグインだと思いますよ。
関連する記事
- AngularJS + Railsで国際化(i18n)
- Rails+JSフレームワークでリアルタイム掲示板を作成してみる(Backbone.js編)
- Ruby on Railsでカンマ付き金額を扱う
- Rails用のgemを作成する手順 (Rails 4.0以降)
- Rails+JSフレームワークでリアルタイム掲示板を作成してみる(Ember.js編)
テスト
テストです3
自分の投稿
要承認の投稿?
初めての投稿
CAPTCHAテストです
さらにテスト
ゲスト
もう一度ゲスト
テスト
自由に投稿できる?
test
答えを間違えてみる