[ransack]複雑な検索機能の実装


はじめに

本記事では、ransackを用いた複雑な検索機能について記述します。
以下の画像のようなものを作成します。

・「名前など」のところには、店名やメニュー名などがキーワードで検索できるようにしました。
・「辛さ(からさ)」では、ActiveHashとしているものとなっています。
・「close」は関係ないので、無視です。

コード

該当箇所記載します。
関係ないところは、省略します。

コントローラー

@q@pなど記載方法は分かれますが、[:q]もあるので、
@qに統一しました。

検索パラメーター(検索する際に入力した内容)のキーを、
:qとしており、queryのイニシャルのことです。

query=質問(by Google先生)

記述し終わったらbinding.pryして、検索してみたら良いと思います。
検索した全ての結果をresultメソッド@foodsとしてインスタンス変数を生成しています。

food_controller.rb
class FoodsController < ApplicationController

  def index

(省略)

    @q = Food.ransack(params[:q])
  end

  def search
    @q = Food.ransack(params[:q])
    @foods = @q.result
  end

(省略)

ビュー

search.html.erb
検索結果をeachメソッドで、すべて表示しています。
また、条件分岐で、検索結果が該当なしの場合は、
デカデカと「Sorry」しました。

ここは特にいうことはありません。

<div class="main">
  <div class="food-contents">
  <h2 class="food-contents-title">検索結果</h2>
    <% if @foods.present? %>
    <ul class="food-lists">
      <% @foods.each do |food| %>
        <li class="list">
          <div class="food-img-content">
          <h2 class="food-post-user">
            <%= link_to user_path(food.user_id) do %>
              <% if food.user.icon.present? %>
                <%= image_tag food.user.icon, class: "icon-img" %>
              <% else %>
                <i class="fas fa-user-circle"></i>
              <% end %>
              <%= food.user.nickname %>
            <% end %>
          </h2>
          <%= link_to food_path(food) do %>
            <%= image_tag food.image, class: "food-img" if food.image.attached? %>
            <div class="food-img-info">
              <h2 class="shop-name">
              <%= food.shop_name%>
              </h2>
              <h2 class="food-name">
              <%= food.food_name%>
              </h2>
            </div>
          <% end %>
          </div>
        </li>
      <% end %>
    </ul>
    <% else %>
      <div class="non">
        <h2 class="non-title">SORRY...</h2>
      </div>
    <% end %>
  </div>
</div>

フォームのerbファイル
ここは何時間も悩みました。
複数のカラムの1つのフォームで検索ができるようにするには、
_or_をつける必要があります。

これをつけずに、カラム間に:とかつけると、
ArgumentErrorがでると思います。
メソッドの引数が正しくない時や数が多かったり、少ない時に発生するエラーですね。

collection_selectにおける引数について

第一引数(メソッド名)
・カラム名やname属性やid属性を決定

第二引数(オブジェクト)
・配列データを指定する
ActiveHashなので、ここをインスタンス変数とかにすると、エラー地獄になります。(震え)
今回では、SpicyLevel.allです。

第三引数(value)
表示する際に参照するDBのカラム名

第四引数(name)
実際に表示されるカラム名

オプションinclude_blank
何も選択していない時に表示される内容
(今回では「--」にしてます。)

それらを踏まえ、以下コードです。
私はここでform_withとサヨナラすることになりました。
いきなりransackで検索機能実装している強者は、出会ってもないと思いますが。

<%# form_with、さよなら %>

<%= search_form_for @q, url: search_foods_path, class: "food-search", id:"pull-down" do |f| %>
  <%= f.label :shop_name_or_shop_name_kana_or_food_name_or_station_cont, '名前など' %>
  <%= f.text_field :shop_name_or_shop_name_kana_or_food_name_or_station_cont, placeholder: "TYPE A KEYWORD" %>
  <%= f.label :spicy_level_id_eq, '辛さ' %>
  <%= f.collection_select :spicy_level_id_eq, SpicyLevel.all, :id, :name, include_blank: '--' %>
  <%= f.submit "SEARCH" %>
<% end %>

以上です。
いかがでしょうか。

終わりに

なかなか手強く、これを実装するのに8時間かかりました。😇
しかし、実装できたときはやはり気持ちいいですねえ。
情報化社会の世の中、検索が不十分なアプリケーションは私は微妙ではないかなと思いましたので、
めげずに頑張りました。

また、
他のサイトを見るとseedファイルを使っている方がおりましたが、
私は、使いませんでした。
まあ、いいか。

以下今回の参考サイトです。
Pikawakaというサイトは本当にわかりやすくてすごいなと思います。

Railsでrake db:seedをやり直す
【Rails】 ransackを使って検索機能がついたアプリを作ろう!
gemのransackで複数カラムを検索対象にする方法
【Rails】ransackの使い方をざっくりまとめてみた
【Rails】検索機能の実装手順
[rails]ransackを使用して検索機能
[Rails]ransackを利用した色々な検索フォーム作成方法まとめ
Rails db:seed二重登録解除
railsのseedの書き方いろいろ

明日も頑張ります!!