LoginSignup
2
2

More than 3 years have passed since last update.

【Rilas】ページネーション機能の実装で勉強したこと。

Last updated at Posted at 2020-12-16

一覧表示画面にページネーション機能をつけた際に勉強になった事を備忘録として残しています。

前提

ページネーション機能をつける前のビューなどです。

コントローラー

事前にソート機能をつけています。

app/controller/stocks_controller.rb
class StocksController < ApplicationController
  helper_method :sort_column, :sort_direction

  def index
    @calendar = Calendar.find(params[:calendar_id])
    @stocks = @calendar.stocks.order("#{sort_column} #{sort_direction}")
    @products = Product.all
  end

  private

  def sort_direction
    %w[asc desc].include?(params[:direction]) ? params[:direction] : 'asc'
  end

  def sort_column
    Stock.column_names.include?(params[:sort]) ? params[:sort] : 'id'
  end

end

ヘルパーメソッド(追記)

大事なヘルパーメソッドの記述を抜かっておりました・・・。

app/helper/stocks_helper.rb
module StocksHelper
  def sort_order(column, title)
    css_class = (column == sort_column) ? "current #{sort_direction}" : nil
    direction = (column == sort_column && sort_direction == 'asc') ? 'desc' : 'asc'
    link_to title, { sort: column, direction: direction }, class: "sort_header #{css_class}"
  end
end

ビュー

app/views/stocks/index.html.erb
    <table>
      <thead>
        <tr>
          <th scope="col"><%= sort_order "display", "陳列" %></th>
          <th scope="col"><%= sort_order "publisher", "出版社名" %></th>
          <th scope="col"><%= sort_order "magazine_name", "雑誌名" %></th>
          <th scope="col"><%= sort_order "num", "冊数" %></th>
          <th scope="col"><%= sort_order "price", "本体価格" %></th>
          <th scope="col"><%= sort_order "i_form", "発行形態" %></th>
          <th scope="col"><%= sort_order "purchased", "買切雑誌" %></th>
        </tr>
      </thead>
      <tbody>
        <% @stocks.each do |stock| %>
          <% if stock.num > 0 %>
                <tr>
                  <td><%= stock.display %></td>
                  <td><%= stock.publisher %></td>
                  <td><%= stock.magazine_name %></td>
                  <td><%= stock.num %></td>
                  <td><%= stock.price.to_s(:delimited) %></td>
                  <td><%= stock.i_form %></td>
                  <td><%= stock.purchased %></td>
                </tr>
          <% end %>
        <% end %>
      </tbody>
    </table>

ページネーションの実装

今回kaminariというページネーション用のgemを使って実装しました。
意外と簡単に実装できました〜。

kaminariのインストール

Gemfileにgem 'kaminari'を追加し、$ bundle installでインストールします。

Gemfile
gem 'kaminari'

gemをインストールした後は一度サーバを再起動しましょう。
Ctrl-cでサーバを止め、rails sでサーバを起動できます。
また、忘れてて右往左往しました・・・。

これでkaminariのインストールは完了です。

ページネーションを表示させる

お次はcontrollerです。
ページネーションを表示させたいデータに.page(params[:page])を追加します。

app/controllers/stocks_controller.rb
def index
  # ページネーションをつけたいデータに.page(params[:page])を追加
  @stocks = @calendar.stocks.page(params[:page]).order("#{sort_column} #{sort_direction}")
end

余談(1.ページに表示するレコード数の変更)

1ページに表示するレコード数は初期値では25件なのだそうです。
controllerに.per(表示したいレコード数)を追加すると変更できるそうです。

例えば、30件表示したい場合は.per(30)と追加。

app/controllers/stocks_controller.rb
def index
  # .per(30)を追加
  @stocks = @calendar.stocks.page(params[:page]).per(30).order("#{sort_column} #{sort_direction}")
end

って感じです。

最後に、viewでページネーションを表示させたいところへ
<%= paginate @stocks %>を追加します。

app/views/stocks/index.html.erb
    <%= paginate @stocks %>
    <table>
 〜〜 省略 〜〜
    </table>

余談(2.表示を日本語に変更する)

ページ番号の前後についている<<Firstとか<Prveは判りづらいと感じたので
こちらを日本語に変更していきます。

config/application.rb
# 〜〜省略〜〜
module Teiki29770(アプリ名です)
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0

    # 日本語の言語設定
    config.i18n.default_locale = :ja
    config.time_zone = 'Tokyo'

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
  end
end

サーバを再起動しましょう!
config/localesに日本語変換用のymlファイルja.ymlを作成して、
以下のコードを追加してみます。

config/locales/ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: " &rsaquo;"
      truncate: "..."

これで表示を日本語に変更できました!やった!!
と、思っていたら・・・。

表示数にズレが出てしまう。

スクリーンショット 2020-12-16 16.17.28.png
なんか少ない・・・。30件表示できるはずなのに・・・。
調べてみると他のページも表示数はまちまちでした。

ビューでの条件式が原因

コントローラーで指定している通り、30件づつデータを送って
ビューのほうで条件式に合うデータのみを表示していることが原因でした。

app/views/stocks/index.html.erb
 〜〜 省略 〜〜
      <tbody>
        <% @stocks.each do |stock| %>
          <% if stock.num > 0 %>⇦ここが原因。
                <tr>
                  <td><%= stock.display %></td>
                  <td><%= stock.publisher %></td>
                  <td><%= stock.magazine_name %></td>
                  <td><%= stock.num %></td>
                  <td><%= stock.price.to_s(:delimited) %></td>
                  <td><%= stock.i_form %></td>
                  <td><%= stock.purchased %></td>
                </tr>
          <% end %>
        <% end %>
      </tbody>
    </table>

なので、コントローラーの方で条件に合うデータだけを先に抽出しておいて
そちらを30件ずつビューへ送る様にします。

app/controller/stocks_controller.rb

  def index
    @calendar = Calendar.find(params[:calendar_id])
    @stocks = @calendar.stocks.where("num > ?",0).page(params[:page]).per(30).order("#{sort_column} #{sort_direction}")

  end
app/views/stocks/index.html.erb
 〜〜 省略 〜〜
      <tbody>
        <% @stocks.each do |stock| %>
          〜〜 if文を削除 〜〜
                <tr>
                  <td><%= stock.display %></td>
                  <td><%= stock.publisher %></td>
                  <td><%= stock.magazine_name %></td>
                  <td><%= stock.num %></td>
                  <td><%= stock.price.to_s(:delimited) %></td>
                  <td><%= stock.i_form %></td>
                  <td><%= stock.purchased %></td>
                </tr>
        <% end %>
      </tbody>
    </table>

これで、しっかりと条件に沿ったデータを表示することができました!
スクリーンショット 2020-12-16 18.33.41.png
ちゃんとソートもできます!

勉強になったこと

MVCの関係性の大事さと共に、役割分担をしっかりとすることの大切さを再確認できました。
ありがとう、ページネーション!

参考にさせていただいたサイト様

https://qiita.com/rio_threehouse/items/313824b90a31268b0074
ありがとうございます!

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