Reverse pagination with kaminari?
Asked Answered
I

3

4

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}.

Important answered 27/1, 2013 at 13:45 Comment(5)
Please upgrade to Rails 3.2.11 ASAPKuster
Normally this problem is solved by having the links say "Older Posts" or "Next Page". Is that something you're open to?Kuster
@JesseWolgamott I am not sure I understand what you mean. Older posts and next page links have nothing to do with the problem I described above. They are just helpers, the problem of having different data apearing on the same pages stays.Important
Sure, no worries then. I think you'll have to edit the kaminari source or go non-kaminari for this. This is not the problem that most anyone ever tries to solve.Kuster
hey I've got a post too #13738545Classics
I
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}
Important answered 17/3, 2013 at 13:47 Comment(0)
S
0

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.

Sterile answered 18/3, 2013 at 10:22 Comment(0)
B
0

Kaminary.paginate_array does not produce query with offset and limit. For optimization reason, you shouldn't use this.

Posted my answer here.

Billetdoux answered 6/4, 2014 at 17:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.