问题
I am using Kaminari 0.13.0 with RubyOnRails 3.2.8.
Lets assume I have a default ordering of my elements by crated_at
, I have 8
elements in my list {a, b, c, d, e, f, g, h}
and I paginate them 3
per page.
By default kaminari will create the following page links 1, 2, 3
linking to {h, g}
, {f, e, d}
, {c, b, a}
.
How do I make kaminari create the page links in reverse order? I want it to produce the links in reverse order 3, 2, 1
still linking to reverse ordered elements {h, g}
, {f, e, d}
, {c, b, a}
.
A bit context on the problem I am trying to solve:
I order elements on pages by created_at. I want to have the elements stay on the same page forever. If I do not use reverse pagination, every time I add new elements the page contents change. So in the above example with default kaminari behaviour if I added more elements to the list {i, j}
then the 1st
page would contain {j, i, h}
, not {h, g}
as it used to. The 2nd
page would contain {g, f, e}
not {f, e, d}
as it used to, etc...
This is bad for bookmaking , SEO, etc.
If I had the described above reverse page numbering, then the 1st
page would still have {c, b, a}
, 3rd
page would be updated with the new element to {i, h, g}
and there would be a new page 4 with one element {j}
.
回答1:
I found the solution:
def index
users_scope = Users.order(:whateva)
@users = reverse_paginate(users_scope, params[:page])
end
def reverse_paginate(scope, page)
if page
page_number = page
else
page_number = Kaminari.paginate_array(scope.reverse).page(1).per(10).num_pages
end
Kaminari.paginate_array(scope.reverse).page(page_number).per(10).reverse!
end
You need to update the kaminari page view _page.html.erb
and add ?page=1
to the url:
url = "#{url}?page=1" if page.number == 1
link_to_unless page.current?, page.number, url, opts = {:remote => remote, :rel => page.next? ? 'next' : page.prev? ? 'prev' : nil}
回答2:
Note: This answer is cross-posted from another Stackoverflow question.
There's a good example repo on Github called reverse_kaminari on github. It suggests an implementation along these lines (Source).
class CitiesController < ApplicationController
def index
@cities = prepare_cities City.order('created_at DESC')
end
private
def prepare_cities(scope)
@per_page = City.default_per_page
total_count = scope.count
rest_count = total_count > @per_page ? (total_count % @per_page) : 0
@num_pages = total_count > @per_page ? (total_count / @per_page) : 1
if params[:page]
offset = params[:page].sub(/-.*/, '').to_i
current_page = @num_pages - (offset - 1) / @per_page
scope.page(current_page).per(@per_page).padding(rest_count)
else
scope.page(1).per(@per_page + rest_count)
end
end
end
All credits go to Andrew Djoga. He also hosted the app as a working demo.
回答3:
Kaminary.paginate_array
does not produce query with offset and limit. For optimization reason, you shouldn't use this.
Posted my answer here.
来源:https://stackoverflow.com/questions/14547991/reverse-pagination-with-kaminari