1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

検索機能の実装

Last updated at Posted at 2023-06-14

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アクションのルーティングを設定する
collectionmember
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>
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?