まえがき
今回の、モデルに新しいメソッドを定義し、7つのアクション以外のものを使うというのはどうやら非推奨みたいです。ただし、こちらの方が私的には簡単に作ることができましたので共有させていただきます。
慣れない点がありますので間違い等がありましたらご指摘いただけると嬉しいです。
目次
・検索フォームの作成
・searchアクションのルーティング設定
・searchメソッドをモデルに定義
・searchアクションをコントローラーに定義
・検索結果画面のビューファイルを作成
検索フォームの作成
まずは検索フォームを付けていきます。今回はform_withを使って書きます。書き方は以下の通りです。
<%= form_with(url: search_sample_path, local: true, method: :get, class: "search-form") do |form| %>
<%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
<%= form.submit "検索", class: "search-btn" %>
<% end %>
一つずつ説明していきます。まずurlと指定してある部分はこの後設定する、searchのルーティングで設定されるplefixを書きます。
plefixをパスとして書く時は文字の最後に**_path**をつけるような書き方をします。
plefixはターミナル上でrails routesというコマンドを入力したときに一番ひだりに書いてあるものです。
次にlocal:trueですが、form_withでは何を指定しなくてもremote: trueになるようなのですが、
remote: trueではXMLHTTPRequestオブジェクトリクエストを自動で送信するので、無効化する為にlocal: trueを指定してあげます。remote:trueだと、非同期通信が発動してしまい、画面が遷移しないようです。
ちなみにXMLHTTPRequestオブジェクトとは
XMLHttpRequest (XHR) は、JavaScriptなどのウェブブラウザ搭載のスクリプト言語でサーバとのHTTP通信を行うための、組み込みオブジェクト(API)である。
ということらしいです。簡単にいうと、非同期なデータ通信をするためのAPIです。
今後Ajaxを使う予定がある人は覚えておいても損はないかもしれません。
ちなみにAjaxは(Asynchronous JavaScript + XML)の略です。
method: getは、フォーム送信時のHTTPメソッド(verb)を指定します。
通常は:getや:postを指定するようです。
searchアクションのルーティング設定
Rails.application.routes.draw do
devise_for :users
root to: 'samples#index'
resources :samples do
resources :comments, only: :create
collection do
get 'search'
end
end
resources :users, only: :show
end
今回はコメント機能の検索をかけるので、samplesコントローラーとcommentsコントローラーがネスト構造になっていることに注意してください。
collection doとはidを付けない書き方です。
今回は検索をするときに詳細の情報は必要ないのでid情報は付けません、もしid情報を付けたい時はmember doというものがあるのでそちらを使いましょう。
searchメソッドをモデルに定義
先ほどルーティングにsearchを設定したので今度はモデルにメソッドを定義していきます。現時点だと、.searchというメソッドは使うことができませんが、モデルで設定することにより、コントローラーで使用することができるようになります。
def self.search(search)
return Sample.all unless search
Sample.where('title LIKE(?)', "%#{search}%")
end
今回はtitleで検索をかけていきます。
モデルの中でメソッドを定義する際に、メソッド名の頭にself.を付けるとコントローラーで使えるクラスメソッドという物になります。
上記でLIKE句とwhereメソッドが出てきました
簡単に説明するとLIKE句とは、曖昧検索と言われる物に使われるもので、前方一致や後方一致などを指定するときに使います。
whereメソッドとは、モデル.where(条件)のように引数部分に条件を指定することで、テーブル内の条件に一致したレコードのインスタンスを配列の形で取得できます。そして今回は条件式に前述したLIKE句を使っています。
ちなみに上記の記述方法をif文を使い、よりわかりやすく書くと下記のようになります。
def self.search(search)
if search
Sample.where('title LIKE(?)', "%#{search}%")
else
Sample.all
end
end
Sampleテーブルから曖昧検索をかけて絞るのか、全てを出すのかという簡単な式を作ることができます。
searchアクションをコントローラーに定義
次はコントローラーにアクションを設定し先ほど定義したsearchメソッド使っていきます。
def search
@sample = Sample.search(params[:keyword])
end
params[:keyword]
と書くことで、formで入力した、:keywordを取得することができます。
もしparamsのなかに何が入っているかを確認したい時は
def search
binding.pry
#このように記述する
@sample = Sample.search(params[:keyword])
end
このようにbinding.pryを起動させ、一度ターミナルでparamsと打って、paramsのなかを確認してみると良いでしょう。
今回はparams[:keyword]にはフォームで入力した文字が入るようになっています。
# 検索結果画面のビューファイルを作成
<%= form_with(url: search_samples_path, local: true, method: :get, class: "search-form") do |form| %>
<%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
<%= form.submit "検索", class: "search-btn" %>
<% end %>
<div class="contents row">
#renderを繰り返し出力する
<% @sample.each do |sample| %>
<%= render partial: "sample", locals: { sample: sample } %>
<% end %>
</div>
このビューファイルではrenderを用いて、効率よく投稿ができるような記述をしています。
ビューファイルで使うrenderは部分テンプレートのことで、
<%= render partial: "sample", locals: { sample: sample } %>
と記述をすることで、_sample.html.erbというファイルを読み込むことができます。
locals: { sample: sample }
はsampleというeach文で定義した変数を部分テンプレートでなんという変数で扱うかという意味です。右側が、each文で定義した変数で、左側のsampleが部分テンプレート先で扱う変数です。
あとがき
あとは、部分テンプレート先で検索結果をどのように表示したいかを記述すれば終了です。
はじめにも書きましたが、7つのアクション以外のものを使って検索機能を作るということは本来推奨されていない方法なので、7つのアクションのみで実装する方法も調べてみてください。
この先インクリメンタルサーチを実装したりするかどうかはまた少し工夫が必要になってきますが、ベースは今回記述した検索機能になります。
この記事が検索機能実装でつまずいてしまった人の助けになれれば幸いです。
ではでは!!