11
3

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 5 years have passed since last update.

kaminariではないバニラなページネーションをやっていく

Posted at

経緯

  • kaminariでやれば良いものをなんか意地はりました。
  • Ruby on Rails 5 アプリケーションプログラミングを読んでいたのですが、limitメソッドとoffsetメソッドを使えばページネーションができると書いてあり、やってみようとしました。

目標形

  • 数字リンク部分は常時3つ表示されるようにする。

(以下、例として総ページ数が5の場合。{}はアクティブな状態)

  1. 初回遷移時(1を押下した時)
  • {1}[2][3][>][≫]
  1. 2を押下した時
  • [<]{2}[3][4][>][≫]
  1. 3を押下した時
  • [≪][<]{3}[4][5][>]
  1. 4を押下した時
  • [≪][<][3]{4}[5][>]
  1. 5を押下した時
  • [≪][<][3][4]{5}

※こんなイメージ(初回遷移時)
名称未設定.png

実装

games_controller.rb
  GAME_SIZE_PER_PAGE = 15

  def index
    @current = params[:page].nil? ? 1 : params[:page].to_i

    @games = Game.all.limit(GAME_SIZE_PER_PAGE).offset(GAME_SIZE_PER_PAGE * (@current - 1))
    @max_page = (Game.all.size.to_f / GAME_SIZE_PER_PAGE).ceil

    @pagination = {}
    @pagination['≪'] = 1 if @current >= 3
    @pagination['<'] = @current - 1 if @current != 1

    if @current + 2 >= @max_page
      @pagination.merge!({@max_page - 2 => @max_page - 2, @max_page - 1 => @max_page - 1, @max_page => @max_page})
      delete_list = [0, -1]
      @pagination.delete_if do |key, value|
        delete_list.include?(value)
      end
    else
      @pagination.merge!({@current => @current, @current + 1 => @current + 1, @current + 2 => @current + 2})
    end

    @pagination['>'] = @current + 1 if @current != @max_page
    @pagination['≫'] = @max_page if @current <= @max_page - 3

  end
index.html.erb
※Bootstrap4の記述も入っている。
  <ul class="pagination justify-content-center">

    <% @pagination.each do |key, value| %>
      <li class="page-item<%= ' active' if value == @current %>">
        <%= link_to key, games_path(page: value), class: 'page-link' %>
      </li>
    <% end %>

  </ul>

ポイント

  • 総ページ数を求めるロジック
    • 要素をページあたりの表示数で割って、総ページ数を求めるが、割ったあまりの分もページを用意する必要があるため、ceilメソッドを使って切り上げる。
@max_page = (Game.all.size.to_f / GAME_SIZE_PER_PAGE).ceil
  • 0ページ目と-1ページ目が発生していたら削除
    • 目標形でいう「4以降を押下した時」は、押下されたリンクを左端に置かずに、[3][4][5]が常に表示されるようにするため、このようなロジックを組んでいる。ただ、これだと0ページ目と-1ページ目が発生する場合がある(例えば総ページ数が1しかない場合など)ため、削除する処理を入れる。
@pagination.merge!({@max_page - 2 => @max_page - 2, @max_page - 1 => @max_page - 1, @max_page => @max_page})
delete_list = [0, -1]
@pagination.delete_if do |key, value|
   delete_list.include?(value)
end
  • pathヘルパーに引数を与えると、クエリパラメータになる
    • どのリンクが押下されたかをクエリパラメータでコントローラーまで運ぶ。この書き方を知らなかったため、個人的には今回一番の学びポイントになった。
<% @pagination.each do |key, value| %>
    <li class="page-item<%= ' active' if value == @current %>">
      <%= link_to key, games_path(page: value), class: 'page-link' %>
    </li>
<% end %>

参考

11
3
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
11
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?