🦋

Rails ransackを使った検索機能の実装

2023/05/23に公開

はじめに

現在チーム開発中、プログラミング2ヶ月目の初学者です🔰
検索機能は必須要件ではないのですが、
今日ははじめてransackを使って検索機能を実装しましたので、メモとして残します!

ヘッダーに作ったため、レイアウト含め結構苦戦しました!
色々なものを見ながら作ったので結構情報がごちゃごちゃになってたり
いらない記述があるかもです、、🥲

ransackとは

検索機能を簡単に実装できるgem
https://activerecord-hackery.github.io/ransack/getting-started/simple-mode/

Gemインストール

Gemfile
gem 'ransack'

bundle installを忘れずに!

コントローラーの実装

application_controller

application_controller
class ApplicationController < ActionController::Base
before_action :search

  def search
    @q = Item.ransack(params[:q])
    @item = @q.result(distinct: true)
    @result = params[:q]&.values&.reject(&:blank?)
  end
end

@result = params[:q]&.values&.reject(&:blank?)

params[:q] の値から空でない値のみを取り出し、@result に代入
params[:q] が存在しない場合、nil を返し、それに対して .values や .reject(&:blank?) を実行!
☝️
ここはメンターさんを活用して聞いたコードなのですが、
これがないと、検索窓で空白で検索した時に全てのデータが出てしまいました。

Ransack は、:q検索パラメータにデフォルトのパラメータ キーを使用します。これはsearch_key、Ransack 初期化ファイル (通常は config/initializers/ransack.rb)でオプションを設定することで変更できます。
引用:https://activerecord-hackery.github.io/ransack/getting-started/simple-mode/#default-search-options

@item = @q.resultの後に、あとにソートを入れたりページネーションを入れたりもできるらしいです🙆🏻‍♀️

searches_controller

public側とadmin側にもsearches_controllerを作ってます。(中身の記述はなし)


ルーティング

public側とadmin側に下記を追加しました。

routes.rb
get "search" => "searches#search"

ビューの実装

検索ボックス

(bootstrapなど入っていて見づらくてすみません!)

views/layouts/_search.html.erb
<% if controller_name != 'sessions' %>
<div class="search_form pe-3">
  <%= search_form_for @q, url: search_path, class:"row justify-content-end" do |f| %>
  <div class="col-md-4 p-0">
    <%= f.search_field :name_cont, class:"form-control" %>
  </div>
  <div class="col-md-1 p-0">
    <button class="btn btn-outline-success" type="submit">
      <i class="fa-solid fa-magnifying-glass"></i>
    </button>
  </div>
  <% end %>
</div>
<% end %>
  • ransackの述語(*にはカラムを代入)
    *_cont contains value 部分一致(内容を含む)

検索結果

まだ簡易的なデザインですが、こんな感じで検索結果のページを作って見ました。
名前のリンクを押すと、商品詳細ページに飛ぶようにしてます!

views/public/searches/search.html.erb
<div class="container">
  <div class='row'>
    <table class="table border table-hover table-inverse">
      <% if @result == [] %>
        <h3 class="mt-3 text-center">検索結果がありません。</h3>
      <% elsif @item.present? %>
      <% search_word = @q.name_cont %>
    <h2 class="mt-3">検索結果 "<%= search_word %>"</h2>
      <thead>
        <tr>
          <th>image</th>
          <th>name</th>
          <th colspan="3"></th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <% @item.each do |f| %>
          <td><%= image_tag f.get_image(200,200), class: "image" %></td>
          <td><%= link_to f.name, item_path(f.id) %></td>
          <td><%= f.price_without_tax.to_s(:delimited) %></td>
        </tr>
        <% end %>
      <% else %>
        <h3 class="mt-3 text-center">検索結果がありません。</h3>
      <% end %>
    </table>
  </div>
</div>

🌱参考にさせていただいた記事

https://abillyz.com/moco/studies/649
https://qiita.com/mmaumtjgj/items/8731a70b3f328770867c
https://pikawaka.com/rails/ransack


あまり自信がなく間違っているかもしれないので
お気づきの点があればコメントなどで教えていただけますと幸いです!
もう3時なのでとりあえず寝ます🥲
おやすみなさい

Discussion