主旨と結論
連番で管理するのではなく、「前へ」「次へ」ボタンを設置しての運用です。
記事のポイントは、データが入っていない状態でページネーション機能を使う際に気をつけること
常に何らかのデータが存在する場合は気にする必要はありません。
下記を実現したい場合に参考になります。
- 最初のページは「前へ」ボタンを消す
- 最後のページは「次へ」ボタンを消す
- 最初で最後のページは両方とも消す←ここで次へ問題が発生します。
なので
当初問題のlast_page?の条件分岐は、
<% unless pagenates.last_page? %>
<a href="<%= path_to_next_page(pagenates) %>">次のページ</a>
<% end %>
のようにしていました。
これだと、データがない状態では、最初で最後のページに次へボタンが表示されてしまうのです。
最終的には下記のようにすればOK
<% unless pagenates.last_page? || paenates.out_of_range %>
<a href="<%= path_to_next_page(pagenates) %>">次のページ</a>
<% end %>
まとめ
- last_page?は、現在ページと総ページ数が同じ時にtrueを返し、違う時にfalseを返す。
- データが存在しない際は、表示されるページ数(current_page)は、1となるが、total_pagesは、0となる。
- そのため、データが存在しない場合、表示されたページが最初で最後のページとなるものの条件分岐にはout_of_rangeを併用する必要がある。
最初で最後のページの戻り値は下記の通り
メソッド | データあり | データなし |
---|---|---|
current_page | 1 | 1 |
total_pages | 1 | 0 |
last_page? | true | false |
first_page? | true | true |
out_of_range | false | true |
解説
結論に書きましたが、last_page?は、最後のページの場合trueを返す、ではありません。
last_page?は、現在ページと総ページ数が同じ時にtrueを返し、違う時にfalseを返すです。
kaminariのソースを確認します。
def last_page?
current_page == total_page
end
これだけではよくわからないので、
- current_pageメソッド
- total_pageメソッド
を確認します。
current_pageメソッド
def current_page
offset_without_padding = offset_value
offset_without_padding -= @_padding if defined?(@_padding) && @_padding
offset_without_padding = 0 if offset_without_padding < 0
(offset_without_padding / limit_value) + 1
rescue ZeroDivisionError
raise ZeroPerPageOperation, "Current page was incalculable. Perhaps you called .per(0)?"
end
これは、offset_without_paddingの値が0になるのでしょうか。
データがないのでpaddingなど出ないはずです。
最後には、
(offset_without_padding / limit_value) + 1
として、0をlimit_valueで割って+1しているので、基本的に戻り値は1以上であることが想像できます。
そして、下記の実行結果を確認すると、1とでていましたのでよしとしましょう。
お分かりの方コメント頂けると幸いです、、、、!!!
<%= @users.current_page %>
total_pagesメソッド
def total_pages
count_without_padding = total_count
count_without_padding -= @_padding if defined?(@_padding) && @_padding
count_without_padding = 0 if count_without_padding < 0
total_pages_count = (count_without_padding.to_f / limit_value).ceil
max_pages && (max_pages < total_pages_count) ? max_pages : total_pages_count
rescue FloatDomainError
raise ZeroPerPageOperation, "The number of total pages was incalculable. Perhaps you called .per(0)?"
end
これも
count_without_paddingが0になるのはわかります。
あとは単純な計算とif文ですね。
戻り値がtotal_pages_countになるのはわかりますので、答えは0。(お分かりの方コメンry...)
そして、下記の結果は0でした。
<%= @users.total_pages %>
まとめ、last_page?メソッドとout_of_rangeメソッド
def last_page?
current_page == total_page
end
データがない状態では、
- current_pageは1
- total_pageは0
となりますので、最初で最後のページで、last_page?を使って条件分岐してしまうと、falseが返ってきます。
そこで登場するのが
- out_of_rangeメソッド
これは
def out_of_range?
current_page > total_pages
end
なので、データがない状態ではtrueが返ってきます。
現在ページの方が合計ページを上回ることって普通ないと思うのですが、今回のようなケースを想定していたのでしょうか。
git_hub、紹介したメソッドが定義されているページ
Git_Hub/kaminari
https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-core/lib/kaminari/models/page_scope_methods.rb