问题
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