1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ransackを用いて複数ワードの空白区切り、フリーワードでの検索機能を実装する

Last updated at Posted at 2021-10-03

はじめに

開発ですぐに忘れそうなことを、簡単に再度調べられるようにするための備忘録です。

やりたいこと

検索機能を簡単に実装できるransackを用いて、
複数のワードを空白区切りで入力された時の検索と
カラムを跨いだフリーワードでの検索を実装したい。

事前知識

例えば、Blogモデルにransackを用いて検索機能を実装する流れとして、

  • カラム名_eq, カラム名_contなどのパラメーターを渡す( params[:q][:title_cont]など )
  • Blog.ransack(params[:q])で検索
  • 検索で得られたオブジェクトに対してresultを用いて、ActiveRecord_Relationに変換する

のような流れで実装していく。

その他、細かな点はソースコードピカワカさんのサイトが参考になりそう。

実装の流れ

  1. 入力された文字列を空白で区切る
  2. 区切った単語と検索したいパラメーターをハッシュに格納
  3. 得られたハッシュをransackに渡す

を新しい検索メソッドとして、実装していく。
また、検索のロジックになってくるため、model側にscopeメソッドとして実装する。

model.rb

  scope :multi_search, -> (freeword) {
    words = freeword.scan(/[[:^space:]]+/)

# ※1
    g = words.map do |word|
      {
        x1_eq: word,
        x2_cont: word,
        x3_cont: word,
        m: "or"
      }
    end
# ※2
    ransack({ m: 'and', g: g, s: 'xxx desc' })
  }

※1:x1~x3は検索したいカラムを指定する
※2:cominatorでandかor検索かを指定できる。また、sのバリューにソートしたい条件を渡すことで、出力のソート条件も指定ができる。

上記で複数ワードの検索が実装できる。

※2021年10月6日、コメントいただいた書き方で、※1、 2をそれぞれ修正いたしました。

最後に、ransackのparams[:q]には、デフォルトでは、カラム名_contなどしか渡せないので、ransackable_scopesに好きなワードを設定する。

model.rb
  def self.ransackable_scopes(auth_object = nil)
    %i[freeword]
  end

これで複数ワードで検索する準備ができたので、
ビュー側で、

view.html.erb
<%= search_form_for @q, url: search_machines_path do |f| %>
  <%= f.search_field :freeword %>
  <%= f.submit %>
<% end %>

コントローラー側で、

controller.rb

@search = Blog.multi_search(params[:q])
@list = @search.result(distinct: true)

とすれば、複数ワード、フリーワードでの検索機能が実装できる。

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?