【Rails】”LIKE ~ OR”を利用した簡易検索バーの実装方法(非同期処理)

プログラミング初心者の勉強ブログ #83

簡易的な検索バーの実装方法を紹介します。自サイト内検索機能を実装する方法はいくつかありますが、今回はgemを使わずに、入力した値でデータベースに検索をかけ、実行結果を非同期通信で画面に反映させるやり方です。パーシャルと「js.erb」ファイルを作成して検索結果後の変数で画面を書き換えていく流れです。

 

目次

[toc]

 

実装内容

検索機能

ブログアプリで、入力されたキーワードと部分一致するブログを検索し表示させる、非同期通信による検索バーの実装です。

大まかな処理の流れは、

  1. キーワード入力後、検索ボタンを押される
  2. 入力されたキーワードで、指定したテーブル内の、部分一致する中身を持つレコードを取り出す(あいまい検索)
  3. 検索結果が変数に格納される
  4. 「js.erb」ファイルに書き込んだJSが、HTMLの書き換え処理を行う
  5. 画面表示が切り替わる

です。

 

コードと解説

Viewのコーディング

viewはメイン、パーシャル、js.erbの3つで構成してます。メインはレンダリングの記述のみで、パーシャルに表示させたい内容、js.erbにHTMLの書き換えコードを書き込みます。

 

blogs/index.html.erb(抜粋)

<%= form_with(url: blogs_path, method: 'get') do |form| %>
 <div class="blog_search">
  <%= form.text_field :keyword, placeholder: "キーワードを入力", class: "search_field" %>
  <%= form.submit '検索', class: "search_btn" %>
 </div>
<% end %>

<section id="search_area">
  <%= render partial: 'index', locals: { blogs: @blogs } %>
</section>

前半部が検索バー、後半部が検索結果表示箇所になります。「form_with」の送信先を「url: blogs_path, method: ‘get’」とすることで、blogsコントローラーのindexアクションが叩かれます。「form.text_field :keyword」で入力内容をパラメータ送信し、コントローラーで「params[:keyword]」として拾えます。

また、JSのセレクタ用に「search_area」というidを持ったdivを作成します。このdivの中身が書き換え対象です。「render partial: ‘index’」で下に書いた「blogs/_index.html.erb」をレンダリング、「locals: { blogs: @blogs }」で@blogsをレンダリング先に飛ばします。

 

blogs/_index.html.erb

<h2>ブログ一覧</h2>
<% blogs.each do |blog| %>
  <%= link_to blog_path(blog.id) do %>
    <%= blog.title %>
    <% if ad.image.url.present? %>
      <%= image_tag(blog.image.url)%>
    <% end %>
    <%= blog.content %>
  <% end %>
<% end %>

ブログ一覧画面を作成します。each文で一覧表示できる状態です。先ほどの「locals: { blogs: @blogs }」で「blogs」の中に「@blogs」が入ってます。

 

blogs/index.js.erb

$("#search_area").html("<%= escape_javascript(render partial: 'index', locals: { blogs: @blogs }) %>")

HTMLの書き換えコードです。index.html.erbで作成したid「search_area」をセレクタにとります。「escape_javascript」は「j」でも大丈夫です。

 

Controllerのコーディング

controllers/blogs_controller.rb(抜粋)

class BlogsController < ApplicationController
 def index
  @blogs = Blog.search(params[:keyword])

  if params[:keyword].present?
   render 'index.js.erb'
  end
 end
end

indexコントローラーを少しいじります。「@blogs = Blog.all」から「@blogs = Blog.search(params[:keyword])」とします。ここで使われているsearchメソッドはこれからBlogモデルに作成する独自メソッドで、このメソッド内でデータベースに検索をかけていきます。

「if params[:keyword].present?」の条件分岐で、検索時(params[:keyword]がコントローラーに届いているとき)のみjsを起動させます。

 

Modelのコーディング

model/blog.rb(抜粋)

class Blog < ApplicationRecord
 def self.search(keyword)
  if keyword
   Blog.where(['title LIKE ? OR content LIKE ?', "%#{keyword}%", "%#{keyword}%"])
  else
   Blog.all
  end
 end
end

「controllers/blogs_controller.rb」で使用するsearchメソッドを作成します。「self」でクラスメソッド化させ、インスタンス生成しなくても、「search」メソッドをmodelクラスにあてることで直接使用できる状態です。「keyword」の有無で条件分岐を行います。

['title LIKE ? OR content LIKE ?', "%#{keyword}%", "%#{keyword}%"]

について、

['カラム名 LIKE ?, "%検索ワード%"]

が元であり、「指定したカラム内で検索ワードと部分一致するレコードを取得」になります。検索ワードを「%」で挟むことで「完全一致」から「部分一致」に変更してます。また、「OR」で繋げることで、複数カラムを検索対象にできます。その場合、カラム名に対応する数分「”%検索ワード%”」をカンマで区切って記述します。「#{}」はRubyを文字列内で反映させるために使用するものです。「シングルクオーテーション」ではなく「ダブルクオーテーション」で囲んだ文字列でないと反応しません。

 

以上のコーディングで実装完了になります。

 

まとめ

検索バーの実装は今回が初めてでした。今思えばスクールのカリキュラムになかったです。簡易的な検索バーなので複雑な検索はできませんが、画面遷移がないので良いです。複雑な検索も行う場合はgemを使うみたいです。オリジナルアプリを一通り作成し終わったら検索機能もgem使いたいと思います。

以上ありがとうございました。

 

 

 

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA