概要
今回は複数テーブルからデータを検索する方法について解説していきます。検索機能を簡単に実装できるransackというgemがありますが、今回は使わずに実装しています。またAPIモードでRailsアプリを作成しているので、Viewのコードは記載しません。
準備編
CustomerとTeamというモデルを作成します。作業手順は別記事にまとめていますので、こちらを参考にしてください。
検索機能の実装編
検索機能といってもどのようなUI(見た目)や要件にするかで実装方法は異なります。今回はよくある2パターンを例に挙げて解説していきます。
例① 検索ボックスが1つの場合
要件は下記の通りです。
- 検索ボックスは1つ
- 検索ワードにCustomer名が入力されたら、合致するCustomer を表示する
- 検索ワードにTeam名が入力されたら、そのTeamに属するCustomerを表示する
- 検索ワードが空の場合、Customer全件表示する
- 部分一致(特定の文字を含むか)
1.Customerモデルにメソッドを追加する
検索を行うメソッドをcustomer.rbに追加します。
# 今回の場合、selfは"Customer"という意味になる
def self.search(keyword)
if keyword != ""
teams = Team.where('name like ?', "%#{keyword}%")
if(teams.present?)
customer_teams = CustomerTeam.where(team_id: teams.ids)
customer_team_id = customer_teams.pluck(:customer_id)
Customer.where(id: customer_team_id)
else
Customer.where('name like ?', "%#{keyword}%")
end
else
Customer.all
end
end
searchメソッドの前にselfがついていますが、これは『クラスメソッド』である印です。今回はCustomer.search(...)のようにクラスに対して、使用したいメソッドなのでselfが必要となります。
# OKな場合(Customerというクラスに対してsearchメソッドを使用している)
@customers = Customer.search(keyword)
# NGな場合(customerというインスタンスに対してsearchメソッドを使用している)
@customers = customer.serach(keyword)
2.コントローラーで検索するメソッドを使う
モデルで作成したメソッドを使います。
class CustomersController < ApplicationController
# GET /customers
def index
keyword = params[:keyword]
@customers = Customer.search(params[:keyword])
render json: @customers
end
end
これで実装は完了です。
paramsに関する補足
params[:keyword]にはユーザーが入力したワードが文字列で入っています。params[:keyword]とすると検索ワードの値が取れるのか確認するため、コントローラーに一文追加してみましょう。
class CustomersController < ApplicationController
# GET /customers
def index
keyword = params[:keyword]
p params # ここを追記
@customers = Customer.search(params[:keyword])
render json: @customers
end
end
次にURLを/customers?keyword=テストとして、再読み込みします。そうするとターミナルには下記のように表示されます。
Parameters: {"keyword"=>"テスト"}
Parametersの部分は”params”と同じなので、このようになります。
params = {"keyword" => "テスト"}
# keywordの中身を取り出したければparams[:keyword]とする
# params[:keyword]
# => "テスト"
例② 検索ボックスが1つ & ラジオボタン(or セレクトボックス)の場合
要件は下記の通りです。
- 検索ボックスは1つ
- ラジオボタンでCustomer or Teamどちらのテーブルから検索するか選択可能
- 部分一致(特定の文字を含むか)
1.コントローラーにメソッドを追加
typeとkeywordで検索できるようにコントローラーに独自メソッドを作成します。
[customers_controller.rb]
def search_by_params
type = params[:type]
keyword = params[:keyword]
if type == "Customer"
@customers = Customer.where('name like ?', "%#{keyword}%")
render json: @customers
elsif type == "Team"
@teams = Team.where('name like ?', "%#{keyword}%")
render json: @teams
else
@customers = Customer.all
render json: @customers
end
end
2.ルーティングを追加
検索するためのルーティングを追加します。
[routes.rb]
Rails.application.routes.draw do
(省略)
get 'search_by_params' => 'customers#search_by_params'
end
挙動の確認をするため、URLを"/search_by_params?type=Team&keyword=サンプル"とし再読み込みします。Team名が"サンプル"のデータが表示されればOKです。
解説は以上です。