LoginSignup
18
18

More than 3 years have passed since last update.

【Rails】kaminari&ransackでページネーションと検索機能を実装

Posted at

【ページネーション】
1ページあたり20件に設定。
スタイルはBootstrap4で実装します。

【検索機能】
投稿一覧から検索とブックマーク済み投稿一覧から検索の2パターン実装していきます。
検索条件はタイトルか本文の部分一致とします。

【事前準備】
・ブックマーク機能を実装しておいてください。
参考資料:【Rails】ブックマーク(お気に入り)機能
・bootstrap4を使用できるように設定しておいてください。
参考資料:BootstrapをRailsに導入してみよう!徹底解説!

環境

Rails 5.2.3
mysql 5.7.28
gem kaminari
gem ransack

実装

それでは実装していきます。

gemの追加

gem kaminari
gem ransack

Gemfileに追加し、bundle install

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

ページネーション実装

まずはページネーションから実装していきます。

ターミナルでkaminariの設定ファイルを自動生成するコマンドを入力します。

ターミナル
$ rails g kaminari:config

これでkaminariの動作を変えるために必要な設定ファイルを生成できます。

次にページネーション用のビューファイルをを自動生成するコマンドを入力します。

ターミナル
$ rails g kaminari:views bootstrap4

これでbootstrap4のページネーションのデザインに合わせたビューファイルが自動で生成されます。

次に1ページあたりのデータ取得数を書き換えます。
デフォルトでは25件のデータを取得する設定になっています。

config/initializers/kaminari_config.rb
# frozen_string_literal: true
Kaminari.configure do |config|
  config.default_per_page = 20 # 25から20に書き換え
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0
  # config.left = 0
  # config.right = 0
  # config.page_method_name = :page
  # config.param_name = :page
  # config.params_on_first_page = false
end

次はコントローラーにpageメソッドを追加していきます。

board_controller.rb
def index
  @boards = Board.includes(:user).page(params[:page])
end

def bookmarks
  @boards = current_user.bookmark_boards.includes(:user).page(params[:page])                  
end

kaminariをインストールしたことでモデルクラスに対してpageメソッドが使用できるようになります。
先ほど設定した1ページあたりのデータ取得件数を引数のparams[:page]に格納し、ビューで表示するようにします。

この時点で1ページ目には20件のデータが表示されているはずです。
2ページ目以降も見れるようにリンクを貼ります。
リンクを貼りたい箇所に<%= paginate @boards %>を記述すればOKです。
Image from Gyazo
サーバーを再起動して、このようなリンクが表示されていれば実装完了です。

日本語化

実装は完了ですが英語の部分を日本語化しておきます。

デフォルトのロケール(言語)を日本語にします。

config/application.rb
module アプリ名
  class Application < Rails::Application
  # 追記↓
    config.i18n.default_locale = :ja

次に日本語訳を設定するファイルを作成・記述していきます。
config/locales/ja.ymlを作成し任意の日本語を記述していきます。

config/locales/ja.yml
ja:
  views:
    pagination:
      first: 最初
      last: 最後
      previous: 
      next: 
      truncate: ...

これで設定が完了したのでサーバーを再起動したら反映されているはずです。

検索機能実装

controllerを編集

boards_controller.rb
def index
    @q = Board.ransack(params[:q]) # 検索オブジェクト作成
    @boards = @q.result.includes(:user).page(params[:page]) # 検索結果(検索しなければ全件取得)
end

def bookmarks
    @q = current_user.bookmark_boards.ransack(params[:q]) # 検索オブジェクト作成
    @boards = @q.result.includes(:user).page(params[:page]) # 検索結果(検索しなければ全件取得
end

viewを編集(検索フォーム)

boards/index.html.erb
<!-- 検索フォーム --> 
<%= render 'search_form', url: boards_path, q: @q %>
boards/bookmarks.html.erb
<!-- 検索フォーム -->
<%= render 'search_form', url: bookmarks_boards_path, q: @q %>
_search_form.html.erb
<%= search_form_for q, url: url do |f| %>
  <div class="input-group mb-3">
    <%= f.search_field :title_or_body_cont, class: "form-control", placeholder: '検索ワード' %>
    <div class="input-group-append">
      <%= f.submit "検索", class: "btn btn-primary" %>
    </div>
  </div>
<% end %>

<%= search_form_for q, url: url do |f| %>のurlを一覧とブックマーク一覧のurlで指定することでその範囲内から検索をすることができます。

<%= f.search_field :title_or_body_cont,...でtitleカラムとbodyカラムのどちらからでも検索が部分的に一致すれば表示されます。
条件はこちらのサイトを参考にしました。
Ransackで簡単に検索フォームを作る73のレシピ

viewを編集(検索結果一覧)

index.html.erb,bookmarks.html.erb共通
<!-- 掲示板一覧 -->
<% if @boards.any? %>
  <div class="row d-flex">
    <%= render @boards %>
  </div>
<% else %>
  <h1><%= '検索結果がありません。' %></h1>
<% end %>
<%= paginate @boards %>

これでインスタンスにデータが存在すれば一覧表示され、なければ検索結果がありませんと表示されます。

まとめ

わりとすんなり実装できたかなと思います。
詰まったとことしては検索範囲を全boardとbookmark_boardで範囲分けする部分でしたが、urlを検索範囲に指定することで解決しました。

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