LoginSignup
1
1

More than 3 years have passed since last update.

【超かんたん】ransackを使って検索機能を実装しよう!

Last updated at Posted at 2021-03-02

ransackを利用して検索機能を実装します。
今回も初心者向けにレシピ投稿アプリを例に作成していきます。

また、検索機能の実装にActive Hashの値も利用するのでActive Hashがわからない方は前回記事にしておりますので、そちらをご覧頂けたらと思います。

完成イメージ

19c0a417740b22b00dc7a7fcfe4ad268.gif

それでは、実装していきましょう!

ransackとは

ransackはRails用の検索機能を実装するためのGem。公式ドキュメント

導入方法

Gemfileに下記を記述しbundle installします。

Gemfile
gem 'ransack'
ターミナル
bundle install

デモデータを投入しよう!

seed.rbにデモデータ生成する記述をしていきます。
category_idとtime_required_idはActive Hashの値と紐付いているカラムになります。

また、time_required_idのFakerがわからない方は前回記事にしておりますので、そちらをご覧頂けたらと思います。
【超かんたん】Fakerを使ってダミーデータを作成しよう!

db/seed.rb
5.times do |n|
  Recipe.create!(
    title: "すし・魚料理#{n}",
    text: "作り方",
    category_id: 1,
    time_required_id: Faker::Number.within(range: 2..6)
  )
end

#中略

5.times do |n|
  Recipe.create!(
    title: "お菓子・スイーツ#{n}",
    text: "作り方",
    category_id: 10,
    time_required_id: Faker::Number.within(range: 2..6)
  )
end
ターミナル
rails db:seed

デモデータの作成完了。
r.jpg

簡易的にindexページに表示します。
in.png

検索機能の実装

ルーティングの設定

まずは検索ページ(search)のルーティングと検索結果を表示するページ(result)のルーティングの設定をしましょう。

7つのアクション以外のルーティングを設定するので、recipesにネストさせます。
今回は、URLにidがつかないのでcollectionを利用します。

config/routes.rb
Rails.application.routes.draw do
  root to: 'home#index'
  devise_for :users
  resources :users
  resources :recipes do
    collection do
      get :search
      get :result
    end
  end
end

コントローラーの編集

以下の記述は公式ドキュメントを参考にしております。

app/controllers/recipes_controller.rb
class RecipesController < ApplicationController
  before_action :search_recipes, only: [:search, :result]

  def index
    @recipes = Recipe.all
  end

  #中略

  def search
  end

  def result
    @results = @q.result
  end

  private
  def search_recipes
    @q = Recipe.ransack(params[:q])
  end
end

params[:q]のキー「:q」でrecipesテーブルからレシピ情報を探し「@q」に格納します。
この@qに対して「.result」とすることで検索結果を取得します。

次にビューファイルを作成していきましょう。

ビューの作成

ビューファイルの作成

ターミナル
touch app/views/recipes/{search.html.erb,result.html.erb}

ビューファイルの編集

今回はCSSの説明は省きます。

検索フォームにはsearch_form_forというメソッドを使います。
form_withのransack版というイメージです。
form_withでは「text_field」ですが、search_form_forだと「search_field」になります。

また、「:カラム名_マッチャ」とすることで条件にあった検索を行います。
_cont」だと「入力された値が含まれている」という意味になり、「_eq」は「入力された値と等しい」という意味のマッチャになります。
その他のマッチャについては公式ドキュメントを参照してください。

collection_selectメソッドについては前回の記事Railsドキュメントを参照してください。

以下のように編集していきます。

app/views/recipes/search.html.erb
<div class="recipe-form">
  <h1 class="text-center">検索する</h1>
  <%= search_form_for @q, url: result_recipes_path do |f| %>
    <div class="form-group">
      <label class="text-secondary">料理名</label><br />
      <%= f.search_field :title_cont, class: "form-control"%>
    </div>
    <div class="form-group">
       <label class="text-secondary">カテゴリー</label><br />
       <%= f.collection_select(:category_id_eq, Category.where.not(id: 0), :id, :name, include_blank: '指定なし') %>
    </div>
    <div class="form-group">
       <label class="text-secondary">所要時間</label><br />
       <%= f.collection_select(:time_required_id_eq, TimeRequired.where.not(id: 0), :id, :name, include_blank: '指定なし') %>
    </div>
    <div class="form-group">
       <label class="text-secondary">フリーワード</label><br />
       <%= f.search_field :text_cont, class: "form-control"%>
    </div>
    <div class="actions">
      <%= f.submit '検索', class: "btn btn-primary" %>
    </div>
  <% end %>
</div>

それでは表示してみましょう。
せ.png

次に検索結果ページを作成していきましょう。
以下のように編集していきます。

app/views/recipes/result.html.erb
<div class="recipes-index text-center">
  <h1 class="result-index">検索結果</h1>
  <% if @results.length != 0 %>
    <% @results.each do |recipe| %>
      <div class="recipe">
        <div class="recipe-title">
          <%= recipe.title %>
        </div>
        <div class="recipe-content">
          カテゴリー: <span class="recipe-category"><%= recipe.category.name %></span>
          所要時間: <span class="recipe-time"><%= recipe.time_required.name %></span>
        </div>
      </div>
    <% end %>
  <% else %>
    該当するレシピはありません
  <% end %>
</div>

if文で該当する検索結果がない場合は「該当するレシピはありません」と表示させるようにしています。
それでは実際に検索してみましょう。

該当する検索結果がある場合

19c0a417740b22b00dc7a7fcfe4ad268.gif

該当する検索結果がない場合

c8e6ad3cfc012c474e3c28ddb7be9cfe.gif

以上で完成です。

1
1
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
1