Reverse pagination with kaminari

旧城冷巷雨未停 提交于 2020-01-01 07:53:25

问题


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?


回答1:


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.




回答2:


One way to solve this problem would be this one: Reverse pagination with kaminari? It does not look very clean nor optimal, but it works :)




回答3:


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 %>



回答4:


Yes, but the method I have come up with isn't exactly pretty. Effectively, you have to set your own order:

Message.page(1).per(3).order("created_at DESC").reverse!

The problem with this approach is twofold:

First the reverse! call resolves the scope to an array and does the query, nerfing some of the awesome aspects of kaminari using AR scopes.

Second, as with any reverse pagination your offset is going to move, meaning that between two repeat calls, you could have exactly 3 new messages send and you would get the exact same data back. This problem is inherent with reverse pagination.

An alternative approach would be to interrogate the "last" page number and increment your page number down towards 1.



来源:https://stackoverflow.com/questions/13738045/reverse-pagination-with-kaminari

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