2012-12-06 15 views
15

Ich möchte Seitennummerierung für ein Messaging-System erstellen, in dem die erste Seite die ältesten Nachrichten enthält, mit nachfolgenden Seiten, die neuere Nachrichten anzeigen.Umgekehrte Paginierung mit Kaminari

Zum Beispiel, wenn normale Paginierung für {a,b,c,d,e,f,g,h,i} mit 3 pro Seite lautet:

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

Dann Paginierung umkehren würde:

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

Ich plane, um die Seiten prepend so das Ergebnis ist das gleiche wie normale Paginierung, nur ab der letzten Seite.

Ist dies mit kaminari möglich?

+0

Warum paginieren Sie nicht einfach den umgekehrten Datensatz? 'YourModel.order (" created_at ASC "). Seite'? – thomasfedb

Antwort

0

Ja, aber die Methode, die ich mir ausgedacht habe, ist nicht gerade hübsch. Effektiv, müssen Sie Ihre eigene Reihenfolge gesetzt:

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

Das Problem bei diesem Ansatz ist eine doppelte:

Zuerst das Gegenteil! Aufruf löst den Bereich zu einem Array und führt die Abfrage durch, nerfing einige der tollen Aspekte von Kaminari mit AR Scopes.

Zweitens, wie bei jeder umgekehrten Seitennummerierung wird sich Ihr Offset verschieben, was bedeutet, dass Sie zwischen zwei Wiederholungsaufrufen genau 3 neue Nachrichten senden können und Sie die exakt gleichen Daten zurückbekommen würden. Dieses Problem ist bei der umgekehrten Paginierung inhärent.

Ein alternativer Ansatz wäre, die „letzte“ Seitennummer abzufragen und Ihre Seitenzahl zu erhöhen, nach unten in Richtung 1.

+0

Etwas wie: 'pages = Message.count% 3; Message.page (Seiten - i) .per (3) .order ("created_at DESC") '? – Trompa

+0

Ausgenommen 'order (" created_at DESC ")' sollte 'order (" created_at ASC ") sein, wenn Sie mit diesem Ansatz fortfahren. –

2

Es gibt ein gutes Beispiel Repo auf Github namens reverse_kaminari auf Github. Es schlägt eine Implementierung in dieser Richtung (Source) vor.

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 

Alle Credits gehen zu Andrew Djoga. Er bewirtete auch die App als a working demo.

1

Kaminary.paginate_array erzeugt keine Abfrage mit Offset und Limit. Aus Gründen der Optimierung sollten Sie dies nicht verwenden.

Stattdessen können Sie dies tun:

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

Wo query_for_message steht für jede Abfrage, die Sie die Datensätze für die Paginierung abrufen verwenden. Zum Beispiel können dies alle Nachrichten einer bestimmten Konversation sein.

Jetzt in der Ansichtsdatei müssen Sie nur @messages in umgekehrter Reihenfolge anzeigen. Zum Beispiel:

<%= render :collection => @messages.reverse, :partial => 'message' %> 
<%= paginate @messages %> 
Verwandte Themen