検索機能があったら便利ですよね。

 

オリジナルアプリケーションに、検索機能があったら良いなと思い勉強していました。

 

私のオリジナルアプリケーションは、投稿するものなので検索ができたら、見たい投稿がすぐに探し出せて便利だなと思いました。

 

これから投稿が増えたら、検索できなかったら大変ですね

まずはフォームの作成からです。

 

app/views/posts/index.html.erb

<%= form_with(url: search_posts_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "投稿を検索する", class: "search-input" %>
  <%= form.submit "検索", class: "search-btn" %>
<% end %>

 

form_with の text_field と submit を使って検索窓と検索ボタンを作成しました。

 

次にルーティングの設定です。

今回は”search”という命名で、7つの基本アクション以外のアクションを定義します。

 

今回の検索機能の場合、詳細ページのような:idを指定して特定のページにいく必要がないため、collection  を使用してルーティングを設定します。

 

config/routes.rb

Rails.application.routes.draw do
  devise_for :users
  root to: 'posts#index'
  resources :posts do
    resources :comments, only: :create
    collection do
      get 'search'
    end
  end
  resources :users, only: :show
end

 

 

次にモデルに、検索する処理を記述した searchメソッドを定義します。

 

app/models/post.rb

class Post < ApplicationRecord
  validates :text, presence: true
  belongs_to :user
  has_many :comments

  def self.search(search)
    if search != ""
      Post.where('text LIKE(?)', "%#{search}%")
    else
      Post.all
    end
  end
end

 

where メソッドと LIKE句を使用します。

 

もし検索フォームに何も入力せずに検索ボタンを押すと、引数で渡される search の

中身は空になります。その場合は else に該当し、その時の全ての投稿を取得して表示させます。

 

次はコントローラーに search アクションを定義します。

 

app/controllers/posts_controller.rb

class PostsController < ApplicationController
  before_action :set_post, only: [:edit, :show]
  before_action :move_to_index, except: [:index, :show, :search]

  #中略#
def search @posts = Post.search(params[:keyword]) end private def post_params params.require(:post).permit(:image, :text).merge(user_id: current_user.id) end def set_tweet @post = Post.find(params[:id]) end def move_to_index unless user_signed_in? redirect_to action: :index end end end

 

Postモデルに書いた search メソッドを呼び出しています。

searchメソッドの引数に params[:keyword] と記述して、検索結果を渡しています。

未ログイン時にトップページへリダイレクトされるのを回避するために before_actionの

except オプションに :search を追加しました。

 

次に検索結果が表示できるようにします。

search.html.erb を作成します。

app/views/posts/search.html.erb

<%= form_with(url: search_posts_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">
  <% @posts.each do |post| %>
    <%= render partial: "post", locals: { post: post } %>
  <% end %>
</div>

 

これで検索機能は完成です。