アプリ: ラーメン屋の写真や情報を友達と共有できるSNS
Ruby: 2.6.5
Rails: 5.2.0
viewに検索フォームを設置する
form_withを使って、検索ワードをposts_controllerのsearchアクションに渡します。
・
・
・
<div class="post_search">
<%= form_with url: search_posts_path, method: :get, local: true do |f| %>
<%= f.text_field :search, class: 'form-control', placeholder: "キーワード検索" %>
<%= f.button :type => "submit" do %>
<i class="fas fa-search"></i>
<% end %>
<% end %>
</div>
・
・
・
ルーティング
routes.rb を下記のようにすることで、
/posts/searchというURL(search_posts_path)にgetリクエストを送ることでposts_controllerのsearchアクションにルーティングされます。
~
~
resources :posts, only: [:new, :create, :edit, :show, :update, :destroy] do
get :search, on: :collection
end
~
~
posts_controller
検索ワードに合致する投稿を@postsで定義。
~
~
def search
@section_title = "「#{params[:search]}」の検索結果"
@posts = if params[:search].present?
Post.where(['shop_name LIKE ? OR nearest LIKE ?',
"%#{params[:search]}%", "%#{params[:search]}%"])
.paginate(page: params[:page], per_page: 12).recent
else
Post.none
end
end
~
~
params[:search]でform_withから渡された検索ワードを受け取ります。
whereメソッドはテーブル内から条件に一致したレコードをすべて返します。
(検索ワードがない場合はPost.noneとし、投稿を取得しないようにしました。)
whereメソッド
whereメソッドでは下記のように
モデル名.where('カラム名 = ?', "値")
第一引数に ? を(プレースホルダーと呼ぶ)、第二引数に条件の値を入れることがあります。
このような書き方をすることで、SQLインジェクションというデータベースのデータを不正に操作する攻撃を防ぐことができるそうです。
whereの第二引数には下記のように
"%#{params[:search]}%"
検索ワードの前後に % を置いています。
こうすることで、「空白文字を含む任意の複数文字列」が検索ワードの前後に含まれても
その文字列を持つレコードを返すことができます。
例
%二郎%
→ 「二郎」「ラーメン二郎」「つけ麺二郎」「ラーメン二郎八王子店」「二郎歌舞伎町店」
どれも該当する。
%二郎
→ 「二郎」「ラーメン二郎」「つけ麺二郎」は該当するが、
「ラーメン二郎八王子店」「二郎歌舞伎町店」は該当しない。
下記のように書くことでshop_nameとnearestという2つのカラムから
検索ワードに該当する文字列を検索し、レコードを返します。
Post.where(['shop_name LIKE ? OR nearest LIKE ?',
"%#{params[:search]}%", "%#{params[:search]}%"])
あとは@postsをapp/views/posts/search.html.erbで表示させるようにしてください。
こんな感じ
↓
参考
【Rails】1つの検索フォームで複数カラムをまたいで検索する方法
【Rails】whereメソッドを使って欲しいデータの取得をしよう!