2012-12-06 6 views
15

Je souhaite créer une pagination pour un système de messagerie dans lequel la première page affichée contient les messages les plus anciens, les pages suivantes affichant les nouveaux messages.Pagination inversée avec kaminari

Par exemple, si la pagination normale pour {a,b,c,d,e,f,g,h,i} avec 3 par page est:

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

Ensuite, on inverse la pagination serait:

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

je prévois de préfixer les pages de sorte que le résultat est le même comme pagination normale, seulement à partir de la dernière page.

Est-ce possible avec kaminari?

+0

Pourquoi ne pas simplement paginer l'ensemble de données inversé? 'YourModel.order (" created_at ASC "). Page'? – thomasfedb

Répondre

0

Oui, mais la méthode que j'ai trouvée n'est pas exactement jolie. En effet, vous devez définir votre propre commande:

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

Le problème avec cette approche est double:

D'abord l'inverse! call résout la portée en un tableau et fait la requête, nerfing certains des aspects impressionnants de kaminari en utilisant des portées AR.

En second lieu, comme avec tout votre inverse pagination décalage va se déplacer, ce qui signifie que entre deux appels répétés, vous pourriez avoir exactement 3 nouveaux messages envoyés et vous obtiendrez exactement les mêmes données en arrière. Ce problème est inhérent à la pagination inverse.

Une autre approche serait d'interroger le numéro de page « dernier » et incrémenter votre numéro de page vers le bas vers 1.

+0

Quelque chose comme: 'pages = Message.count% 3; Message.page (pages - i) .per (3) .order ("created_at DESC") '? – Trompa

+0

Sauf 'order (" created_at DESC ")' devrait être 'order (" created_at ASC ")' si vous allez suivre cette approche. –

2

il y a un bon exemple repo sur Github appelé reverse_kaminari sur GitHub. Il suggère une implémentation selon ces lignes (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 

Tous les crédits vont à Andrew Djoga. Il a également hébergé l'application en tant que a working demo.

1

Kaminary.paginate_array ne génère pas de requête avec décalage et limite. Pour des raisons d'optimisation, vous ne devriez pas l'utiliser.

place, vous pouvez le faire:

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

query_for_message représente toute requête que vous utilisez pour récupérer les enregistrements pour la pagination. Par exemple, il peut s'agir de tous les messages d'une conversation particulière.

maintenant dans le fichier de vue, il vous suffit d'afficher @messages dans l'ordre inverse. Par exemple:

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