Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse pagination with kaminari

I want to create pagination for a messaging system in which the first page shown contains the oldest messages, with subsequent pages showing newer messages.

For example, if normal pagination for {a,b,c,d,e,f,g,h,i} with 3 per page is:

{a,b,c}, {d,e,f}, {g,h,i}

Then reverse pagination would be:

{g,h,i}, {d,e,f}, {a,b,c}

I plan to prepend the pages so the result is the same as normal pagination, only starting from the last page.

Is this possible with kaminari?

like image 841
Nick Ginanto Avatar asked Dec 06 '12 06:12

Nick Ginanto


2 Answers

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

Instead you can do this:

@messages = query_for_message.order('created_at DESC').page(params[:page]).per(3)

Where query_for_message stands for any query which you use to retrieve the records for pagination. For example, it can be all the messages of a particular conversation.

Now in the view file, you just need to display @messages in the reverse order. For example:

<%= render :collection => @messages.reverse, :partial => 'message' %>
<%= paginate @messages %>
like image 112
Musaffa Avatar answered Oct 22 '22 05:10

Musaffa


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.

like image 39
Thomas Klemm Avatar answered Oct 22 '22 04:10

Thomas Klemm