Reverse pagination with kaminari?

梦想与她 提交于 2020-01-13 03:42:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!