【Rails】あいまい検索機能実装の流れを詳しく解説

「【Rails】あいまい検索機能実装の流れを詳しく解説」のアイキャッチ画像

本記事では、LIKE句を利用した「あいまい検索機能」の実装手順を、アプリ制作を通して詳しく解説します。


完成画面


あいまい検索機能実装の流れ


LIKE句を利用した「あいまい検索機能」は、大まかに以下流れで実装していきます。

①検索フォーム作成
②コントローラ作成
③ルーティング設定
④メソッド作成
⑤検索結果画面の作成

実装手順

⓪はじめに


コーディングはhaml/Scssを利用しています。

商品情報一覧が格納されている「itemsテーブル」から、あいまい検索を通して任意の商品情報を検索、表示させる実装を行なっています。

また本記事で紹介する検索機能について、MVCの概念図に照らし合わすと、大まかには以下の流れになります。

a)検索フォームに、検索する文字列を入力
b)ルーティング、コントローラ、モデルの順に、パラメータ(検索文字列)を渡す
c)SQLで、パラメータのあいまい検索を実行
d)モデルを通してデータベースから取得したデータを、コントローラはビューに渡す
e)リクエストされたデータを検索結果画面として表示


※MVC概念図の番号と、本記事の実装手順の番号は関係ありません


それではこの構造を頭に入れた上で、実装していきます。


①検索フォーム作成


はじめに、検索フォームを作成します。

検索フォームに入力された文字列を、
name: “keyword”として、items/searches#index に送信しています。

※「items/_searchbar.html.haml」は、「items/index.html.haml 」から呼び出している、フォーム専用の部分テンプレートです。

= form_with(url: items_searches_path, local: true, method: :get) do |f|
  %input.search__input{name: "keyword", placeholder: 'キーワードから探す'}
  %button{type: 'submit'}
    .icon
      = image_tag 'icon/icon-search 1.png', class: 'icon-image'


②コントローラ作成


searchesコントローラを作成します。

rails g controller items::searches

items::searchrs について

itemsディレクトリ配下に items/searches_controller.rb を作成する記述です。

本アプリケーションにおける「検索」は、「商品の検索」「ユーザーの検索」など複数の種類が考えられます。そして今回は「商品の検索」機能を実装しますが、それを区別できるよう、「商品」に関するitemsディレクトリを用意し、その配下に searchesコントローラを作成した、という訳です。


次に、コントローラに以下を記述します。

①の検索フォームに入力された文字列を params[:keyword] で受け取り、その文字列をitemsテーブルで検索をする、という処理を @items に格納します。


※searchは自作メソッドのため、処理を定義する必要があります。これは④で行いますので、一旦次へ進みます。

class Items::SearchesController < ApplicationController
  def index
      @items = Item.search(params[:keyword])
      @search_word = params[:keyword]
  end    
end

Items::SearchesController について

1行目に「class Items::SearchesController < ApplicationController」とあります。この「Items::」を名前空間(namespace)と呼びます。③で使いますので、覚えておきましょう。



③ルーティング設定


②のsearchesコントローラのindexアクションで検索した値を表示します。

namespace :items do
  resources :searches, only: :index
end

名前空間(namespace)について

今回、searchコントローラは、検索対象の区別のため、itemsディレクトリ配下(1つ下の階層)に作成しました。そのためルーティング設定方法も通常とは異なり、以下のように記述します。

namespace :  “②で名前空間に指定したコントローラー名”  do
 “ルーティング設定”
end



④メソッド作成


if文で条件分岐処理をします。

まず検索フォームから値を受け取った場合、Itemテーブルのnameカラムにおいて、あいまい検索を行なっています。

そして値が存在しない場合は、すべての商品情報を返す処理を行なっています。

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

モデルにメソッド定義を記述している理由

自作のsearchメソッドは、実際のところ、searches_controller.rb に記述しても同様の処理をしますが、主に可読性の観点で、モデルに記述することが望ましいです。

単純な仕組みのアプリケーションであれば問題ないですが、複雑になると、コントローラ内の記述量も多くなってしまいます。そのような場合に、今回のif文のような処理もコントローラにまとめて記述してしまうと、煩雑になり各コードの役割を把握しづらくなる可能性があるからです。

self について

modelクラス内でメソッド定義する場合、「def self.メソッド名」のように記述すると、クラスメソッドとなります。クラスメソッドは、主にクラスで共通の情報を使った処理(レコードの検索など)に使用します。

故に今回の場合もselfはクラス自身を返すので、self.searchは、Item.searchと同義となります。



⑤検索結果画面の作成


検索結果画面です。


ヘッダー、サイドメニュー、商品一覧は部分テンプレートを使用しています。ちなみにここで呼び出しているファイル群は、以下の階層構造となっています。

 items
    _header.html.haml
    searches
      index.html.haml ⇦ 編集ファイル
      _sideMenuu.html.haml
      _searchedItems.html.haml


※このhtmlは一例ですので、適宜調整ください。

= render 'items/header'
.search
  .search-contents
    = render 'sideMenu'
    .search-main
      %h2.search-main__title
        -if @search_word.present?
          = @search_word
          %span の検索結果
        -else
          = "検索結果"
      .search-main__itemsCnt
        = "1-#{@items.count}件表示"
      = render 'searchedItems'


おわりに


LIKE句を利用した「あいまい検索機能」の実装手順は以上になります。

中でもコントローラとモデルを分類する点は、少々分かりづらいですが、大切な点の1つかと思います。

今回のように、if文による条件分岐や、何か計算が必要な際は、出来るだけモデルに記述しましょう。

実装完了後は、単体テストの実施もおすすめします。


また検索機能の実装は、高度な検索機能を実装をできる「ransack」というgemを使用した方法もあります。実装手順は以下にまとめていますので、よろしければご参照ください。