検索機能があったら便利ですよね。
オリジナルアプリケーションに、検索機能があったら良いなと思い勉強していました。
私のオリジナルアプリケーションは、投稿するものなので検索ができたら、見たい投稿がすぐに探し出せて便利だなと思いました。
これから投稿が増えたら、検索できなかったら大変ですね
まずはフォームの作成からです。
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>
これで検索機能は完成です。