記事の概要
投稿された記事を文字列で検索し、検索された投稿記事を一覧表示する機能の実装方法をまとめた。テーブルの特定カラムを文字列検索対象としている。複数カラムを対象とした検策もできる。
検索の流れ
検索フォームから検索ワードを入力し送信する。
→ 検索ワードが格納されたparamsをコントローラーで受取り、検索メソッドに渡される。
→ 検索メソッドを実行、モデルから文字列検索結果を取得、コントローラでインスタンス変数に代入。
→ ビューでインスタンス変数が展開されて表示。
実装手順
実装手順は下記の通り。
①ルーティングの設定
②検索メソッドをモデルに定義
③検索アクションをコントローラーに定義
④検索フォームをビューに記述
⑤検索結果の表示をビューに記述
①ルーティング設定
検索表示機能はarticlesコントローラーのsearchアクションとして定義する。collectionメソッドで設定する。
Rails.application.routes.draw do
devise_for :users
resources :articles do
#以下、collectionでsearchアクションへのルーティング設定
collection do
get 'search'
end
end
end
②検索メソッドをモデルに定義
投稿記事を扱うArticleモデルの中に検索メソッドを定義する。searchメソッドと命名。
whereメソッドとLIKE句を使用して、特定のレコードを取得できるようにする。ここでは、articlesテーブルにtextカラムがあるとして、これを検索対象カラムとしてwhereの引数部分に条件を指定する。
class Article < ApplicationRecord
def self.search(search)
if search != ""
Article.where('text LIKE(?)', "%#{search}%") #
else
Article.all
end
end
end
なお、引数searchには下で実装する検索フォームから届けられるパラメータが入る。searchの中身が空だった場合の条件分岐もしておいた。
③searchアクションをコントローラーに定義
articlesコントローラーにsearchアクションを定義する。
class ArticlesController < ApplicationController
def search
@articles = Article.search(params[:keyword])
end
end
④検索フォームをビューに実装
indexビューに検索フォームを実装することとする。下記の記述により、検索フォームから文字列を送信するとparams[:keyword]に格納されてsearchメソッドに渡され、Articleモデルに対して文字列検索、レコードの取得が実施される。
<%= form_with(url: search_articles_path, local: true, method: :get ) do |form| %>
<%= form.text_field :keyword %>
<%= form.submit "検索" %>
<% end %>
⑤検索結果をビューに表示させる
検索結果をsearchビューに表示させる。searchメソッドの結果取得されたレコードが格納されているインスタンス変数をeachメソッドで展開する。検索フォームも表示させたままとする。
<%= form_with(url: search_articles_path, local: true, method: :get ) do |form| %>
<%= form.text_field :keyword %>
<%= form.submit "検索" %>
<% end %>
# 以下、検索結果の一覧表示の記述
<div>
<% @articles.each do |article| %>
<%= article.title %>
<%= article.text %>
# 省略
<% end %>
</div>
一つの検索フォームで複数のカラムを対象に検索する
上記ではarticlesテーブルのtextカラムを検索対象としていたが、例えばtitleカラムも検索対象としたいとする。複数のカラムを跨いで検索したい場合は以下のように記述する。
class Article < ApplicationRecord
def self.search(search)
if search != ""
# where(['カラム名 LIKE(?) OR カラム名 LIKE(?)', "%#{search}%", "%#{search}%"])のように記述。
# 検索対象カラムの数だけ"%#{search}%"を記述。
Article.where(['text LIKE(?) OR title LIKE(?)',"%#{search}%","%#{search}%"])
end
else
Article.all
end
end
end