LoginSignup
1

More than 1 year has passed since last update.

posted at

【Rails】ransackを使わずに1つの検索バーで複数テーブルのデータを検索する

本記事は 駆け出しエンジニアの第一歩!AdventCalendar2020 9日目の記事です。

作りたいもの

下図のように一つの検索バーで複数のテーブルのデータを取得する機能を実装します。
下図ではMagicテーブル、Productテーブル、Userテーブルの3つのテーブルに検索をかけて、それぞれのテーブルで検索条件にヒットするデータを取得し、タブで表示を切り替えています。

image.png

image.png

やることまとめ

1.検索機能のルーティングを設定する。
2.ビューに検索バーを実装する。
3.コントローラに検索機能を実装する。

1.検索機能のルーティングを設定する

検索ボタンがクリックされた時に、どのコントローラのどのアクションを呼び出すかをroute.rbに記載します。
下記例では、homes_controller.rbのsearchアクションを呼び出すようにしています。

route.rb

# 検索機能実施
get '/search' => 'homes#search', as: 'search'

2.ビューに検索バーを実装する

次に検索フォームを用意します。
私の場合はヘッダーに検索フォームを表示させたかったので、_header.html.erbに下記コードを実装しました。

_header.html.erb

<%= form_with url: search_path, method: :get, local: true do |f| %>

  <!-- 検索フォーム -->
  <%= f.text_field :content, :placeholder => "マジック動画タイトル、商品名、ユーザー名で検索" %>

  <!-- 検索ボタン -->
  <%= f.button :type => "submit" do %>
    <i class='fas fa-search'></i>
  <% end %>

<% end %>

解説


<%= form_with url: search_path, method: :get, local: true do |f| %>

form_withヘルパーを用いて、検索条件をコントローラまで渡してあげます。
ここでは、URLに/searchを指定し、getメソッドでアクセスするという内容を書いています。


<!-- 検索フォーム -->
<%= f.text_field :content, :placeholder => "マジック動画タイトル、商品名、ユーザー名で検索" %>

f.text_fieldは検索フォームの検索ワードを入力するinput要素を指しています。
入力した検索ワードは:contentに格納されます。(後ほどコントローラで開封します。)


<!-- 検索ボタン -->
<%= f.button :type => "submit" do %>
  <i class='fas fa-search'></i>
<% end %>

form_withヘルパーではsubmitボタンをクリックすると、指定のルーティング先へ遷移するようになっています。
ここではそのsubmitボタンを虫眼鏡アイコンにする処理を書いています。

3.コントローラに検索機能を実装する

コントローラでは、form_withヘルパーより送られてきた検索ワード(:content)を受け取り、それを基に3つのテーブルそれぞれで検索をかけています。

homes_controller.rb

# 検索機能
def search
  # 検索ワード
  content = params['content']
  # 投稿検索結果
  @magics = partical_magic(content)
  # 商品検索結果
  @products = partical_product(content)
  # ユーザー検索
  @users = partical_user(content)
end

private

# 投稿検索
def partical_magic(content)
  Magic.where('title LIKE ?', "%#{content}%")
end

# 商品検索
def partical_product(content)
  Product.where('name LIKE ?', "%#{content}%")
end

# ユーザー検索
def partical_user(content)
  User.where('display_name LIKE ?', "%#{content}%")
end

解説


# 検索ワード
content = params['content']

form_withヘルパーから送られてきたパラメータ:contentの中身、すなわち検索ワードをcontent変数に格納しています。


# 投稿検索結果
@magics = partical_magic(content)
# 商品検索結果
@products = partical_product(content)
# ユーザー検索
@users = partical_user(content)

検索結果用のインスタンス変数を3つ用意し、それぞれに検索結果を格納しています。
それぞれの式の右辺では検索を行うメソッドに先ほど格納したcontent変数を引数として渡しています。


# 投稿検索
def partical_magic(content)
  Magic.where('title LIKE ?', "%#{content}%")
end

# 商品検索
def partical_product(content)
  Product.where('name LIKE ?', "%#{content}%")
end

# ユーザー検索
def partical_user(content)
  User.where('display_name LIKE ?', "%#{content}%")
end

それぞれのテーブルに対して検索を行い、データを返すメソッドです。
モデル名.where('[検索対象カラム] LIKE ?', "%#{content}%")
という式になっています。
上記例は部分一致検索となっております。

おわりに

検索結果画面も載せられればと思ったのですが、かなり複雑になっていたので今回は割愛させてもらいました…汗

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1