【Rails】ransackを使って検索機能を追加する

検索した後に結果が残ったままだと邪魔な場合もあるので、非同期(Ajax)で検索結果クリアボタンも追加する。

今回のアソシエーションとカラム

app/models/user.rb
has_many :projects, dependent: :destroy

ユーザー(1)がプロジェクト(多)を持っている。

app/models/project.rb
belongs_to :user

userテーブルの display_name と、projectsテーブルの title

検索機能

Gemを入れる

Gemfile
gem 'ransack'
Terminal
bundle install

controllerを編集

params[:q] を一回 @params に入れているのは、viewで <% if @params.present? %> として検索していない時に勝手に一覧が表示されないようにするため。

app/controllers/projects_controller.rb
@params = params[:q]
@search = Project.ransack(@params)
@result = @search.result(distinct: true)

検索メソッド

たくさんあるので一部のみ記載。

検索方法 意味
or または
count 部分一致
eq 等しい
not_eq 等しくない
lt より小さい
lt_eq より小さい(含む)
gt より大きい
gt_eq より大きい(含む)

詳しくはREADME↓

activerecord-hackery/ransack
Object-based searching. . Contribute to activerecord-hackery/ransack development by creating an account on GitHub.

viewを編集

controllerで @search = Project.ransack(@params) としてプロジェクトを取り出しているので、プロジェクトの title はそのまま出せるがユーザーの display_nameuser_display_name としないと見つからなくてエラーになる。(基本的なことだけど一応記載)

required: true は空検索しないようにするために。(空だった場合ポップアップが出る)

絶対に空検索したくない場合はcontrollerでparamsの値を見る方が良い。

検索結果のviewをパーシャルで呼んでいる理由は、後でクリアボタンを追加してAjaxで検索結果を消すため。

app/views/projects/index.html.erb
<div>
  <%= search_form_for @search do |f| %>
    <%= f.search_field :user_display_name_or_title_cont, required: true %>
    <%= f.submit "検索" %>
  <% end %>
</div>

<%= render "search_result" %>

内容は適宜に。

app/views/projects/_search_result.html.erb
<div>
  <% if @params.present? %>
    <p>検索結果:<%= @result.count %>件</p>
    <% @result.each do |result| %>
      <div>
        <p>表示名:<%= result.user.display_name %></p>
        <p>タイトル:<%= result.title %></p>
      </div>
    <% end %>
  <% end %>
</div>

ここまでで検索機能自体は完成!

クリアボタン(Ajax)

ここからクリアボタンを追加していく。

ルーティング

config/routes.rb
patch "projects/reload", to: "projects#reload"

viewを編集

<div id=”reloadAjax”></div>で囲っている中に、クリアボタンとクリアしたいもの(先程書いた検索結果)を入れる。

app/views/projects/_search_result.html.erb
<div id="reloadAjax">
  <%= button_to "/projects/reload", method: :patch, remote: true do %>
  <span>クリア</span>
  <% end %>

</div>

$(“#reloadAjax”) のidと <div id=”reloadAjax”> が紐付いている。

クリアボタンと検索結果が入っているパーシャルを呼んで、このパーシャルがindex.html.erbで表示される。

app/views/projects/reload.js.erb
$("#reloadAjax").html("<%= j(render("search_result")) %>");

参考にしたサイト

【Rails】タグの再読み込みボタン(Ajax通信)
個人開発のWebアプリ「...
タイトルとURLをコピーしました