Railsメモ(11) : Ransackで検索機能を追加する
Railsで検索機能を追加するにはRansackを使用するのがよいらしいので試してみる。
Gemfile
に下記行を追加してbundle install
する。
gem 'ransack'
まずコントローラのapp/controllers/songs_controller.rb
を編集する。
class SongsController < ApplicationController def index @q = Song.ransack(params[:q]) @songs = @q.result.page(params[:page]) end end
続いて検索用のフォームを追加するためにビューのファイルを編集するが、今回はNavbarに追加してみるのでapp/vies/layouts/application.html.erb
を編集する。
試しにtitleカラムとdisplay_artistカラムに対して文字列を含むレコードを検索するフォームを追加してみる。文字列を含むはcont
なので、titleカラムに対して検索する場合はtitle_cont
のようになる。
… <div class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <%= link_to 'Billboard', root_path, class: 'navbar-brand' %> </div> <%= search_form_for @q, html: { class: 'navbar-form navbar-left' } do |f| %> <div class="form-group"> <%= f.search_field :title_cont, class: 'form-control', placeholder: 'title' %> </div> <div class="form-group"> <%= f.search_field :display_artist_cont, class: 'form-control', placeholder: 'display_artist' %> </div> <%= f.submit class: 'btn btn-default' %> <% end %> </div> </div> …
編集後アクセスしてみるが下記エラーが発生。どうやら名前付きルートがないことが原因らしいのでconfig/routes.rb
を編集する。
ActionView::Template::Error (undefined method `songs_path' for #<#<Class:0x007f4021f537d8>:0x007f4021f52ae0>):
… # get 'songs/index' # 編集前 match '/songs', to: 'songs#index', via: 'get' …
再度アクセスすると図のように検索フォームが表示され、
例えば、titleカラムに"happy"という文字列を含むレコードを正しく検索できている。
Ransackの検索条件
基本的な検索条件の書き方は下記ページに書いてあるが、以下の条件が指定できる。
Basic Searching · activerecord-hackery/ransack Wiki · GitHub
- eq (equals)
- matches
- lt (less than)
- lteq (less than or equal to)
- in
- cont
- cont_any (contains any)
- start (starts with)
- end (ends with)
- true
- false
- present
- null
また、複数のカラムを組み合わせたい場合は以下のようにand
やor
でつなぐ。
<%= f.search_field :title_and_display_artist_cont, class: 'form-control', placeholder: 'title' %> <%= f.search_field :title_or_display_artist_cont, class: 'form-control', placeholder: 'title' %>
検索可能なカラムを指定
特に何も指定しないと以下のように全てのカラムが検索可能になってしまい、クエリパラメータを直接書き換えれば検索ができてしまう。
これは意図しない不具合を引き起こすかもしれないのでransackable_attributes
を使用して検索可能なカラムを指定する。
[1] pry(main)> Song.ransackable_attributes [ [0] "id", [1] "title", [2] "display_artist", [3] "ranking", [4] "year", [5] "created_at", [6] "updated_at" ]
class Song < ActiveRecord::Base def self.ransackable_attributes(auth_object = nil) %w(title display_artist) end end
[1] pry(main)> Song.ransackable_attributes [ [0] "title", [1] "display_artist" ]
- 作者: すがわらまさのり,前島真一,近藤宇智朗,橋立友宏
- 出版社/メーカー: 技術評論社
- 発売日: 2014/06/06
- メディア: 大型本
- この商品を含むブログ (8件) を見る