はじめに
検索機能を実装するために gem を作っていたんだけど、 何を思ったか検索フォームを実装する gem を Google 先生に質問してしまい、 Ransack という gem を知ってしまった。
自作の gem より高機能そうだったんで、ライバル調査という名目で試してみた。
Ransack のインストール
Gemfile に下記を追加し、bundle を実行。
gem "ransack"
検索機能の実装
検索対象のモデルを用意
class Product < ActiveRecord::Base attr_accessible :name, :description, :price has_many :comments end class Comment < ActiveRecord::Base attr_accessible :product_id, :username, :body, :rate belongs_to :product end
コントローラーを修正
search メソッドと result メソッドが使えるようになっている。
class ProductsController < ApplicationController ... def index # 検索フォームの入力内容で検索する @q = Product.search(params[:q]) # 重複を排除 @products = @q.result(distinct: true) end ... end
params にキー q が存在しないときは全データ取得していた。
ビューに検索フォームを配置
search_form_for という検索フォームを作成するためのヘルパが提供されている。
<%= search_form_for @q do |f| %> <div class="control-group"> <%= f.label :name_cont %> <div class="controls"> <%= f.text_field :name_cont %> </div> </div> <div class="control-group"> <%= f.label :price_gteq %> <div class="controls"> <%= f.number_field :price_gteq %> </div> </div> <div class="control-group"> <%= f.label :price_lteq %> <div class="controls"> <%= f.number_field :price_lteq %> </div> </div> <%= f.submit %> <% end %>
使い方は form_for とたいして変わらない。
たったこれだけで実装完了
ブラウザで表示してみる。
price の範囲を入力して Search をクリック。
おお、ちゃんと絞り込まれてるね。
アソシエーションにも対応していた
検索フォームを次のように作成すると、 belongs_to や has_many で関連付けているモデルの属性も使って 検索できた。
<%= search_form_for @q do |f| %> <div class="control-group"> <%= f.label :comments_username_cont %> <div class="controls"> <%= f.text_field :comments_username_cont %> </div> </div> <%= f.submit %> <% end %>
こいつはスゴイ。
まとめ
Ransack を使えば Rails アプリに検索機能を簡単に実装できた。 値の一致だけでなく、比較や、値を含むかどうかでも検索でき、 さらにアソシエーションにも対応しているという高機能っぷり。 ユーザーの入力でモデルを検索するだけなら、Ransack 使えば十分だな。
似たような gem を作っていたけど、機能はだいぶ Ransack が上。 ピボットが必要かなぁ。