index.html.erbを編集する
検索窓と検索ボタンを作成する。
app/views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form| %>
<%= form.text_field :keyword, placeholder: "検索する", class: "search-input" %>
<%= form.submit "検索", class: "search-btn" %>
<% end %>
searchアクションのルーティングを設定する
collectionとmember
collectionとmemberは、ルーティングを設定する際に使用できます。
これを使用すると、生成されるルーティングのURLと実行されるコントローラーを任意にカスタムできる。
collectionはルーティングに:idがつかない、memberは:idがつくという違いがある。
(詳細ページのような:idを指定して特定のページにいく必要がない場合はcollectionを使用してルーティングを設定する)
【例】collectionで定義した場合
Rails.application.routes.draw do
resources :tweets do
collection do
get 'search'
end
end
end
【例】memberで定義した場合
Rails.application.routes.draw do
resources :tweets do
member do
get 'search'
end
end
end
routes.rbを以下のように編集する
config/routes.rb
Rails.application.routes.draw do
devise_for :users
root to: 'tweets#index'
resources :tweets do
resources :comments, only: :create
collection do
get 'search'
end
end
resources :users, only: :show
end
検索のメソッドをモデルに定義する
モデルに、検索する処理を記述したメソッドを定義。
メソッド名はsearchメソッドとする。
whereメソッド
モデルが使用できる、ActiveRecordメソッドの1つ。
【例】whereメソッド
モデル.where('検索対象となるカラムを含む条件式')
複数のカラムを1つの検索フォームだけで検索したい場合は下記のようにすればできる。
適切なオブジェクト名.where(['検索したいカラム名 ? OR 検索したいカラム名 LIKE ? OR 検索したいカラム名 LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
検索したいカラムが3つある場合は、"%#{search}%"も3つつければ1つのフォームで複数カラムまたいで検索できる!!
LIKE句
LIKE句は、曖昧(あいまい)な文字列の検索をするときに使用するもので、whereメソッドと一緒に使う。
app/models/tweet.rb
class Tweet < ApplicationRecord
validates :text, presence: true
belongs_to :user
has_many :comments
def self.search(search)
if search != ""
Tweet.where('text LIKE(?)', "%#{search}%")
else
Tweet.all
end
end
end
searchアクションをコントローラーに定義する
app/controllers/tweets_controller.rb
class TweetsController < ApplicationController
before_action :set_tweet, only: [:edit, :show]
before_action :move_to_index, except: [:index, :show, :search]
def index
@tweets = Tweet.includes(:user).order("created_at DESC")
end
def new
@tweet = Tweet.new
end
def create
Tweet.create(tweet_params)
end
def destroy
tweet = Tweet.find(params[:id])
tweet.destroy
end
def edit
end
def update
tweet = Tweet.find(params[:id])
tweet.update(tweet_params)
end
def show
@comment = Comment.new
@comments = @tweet.comments.includes(:user)
end
def search
@tweets = Tweet.search(params[:keyword])
end
private
def tweet_params
params.require(:tweet).permit(:image, :text).merge(user_id: current_user.id)
end
def set_tweet
@tweet = Tweet.find(params[:id])
end
def move_to_index
unless user_signed_in?
redirect_to action: :index
end
end
end
検索結果画面のビューを作成
app/views/tweetsディレクトリの配下にsearch.html.erbを作成し
検索結果を表示するように記述する。
app/views/tweets/search.html.erb
<%= form_with(url: search_tweets_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">
<% @tweets.each do |tweet| %>
<%= render partial: "tweet", locals: { tweet: tweet } %>
<% end %>
</div>