2012-12-06 16 views
15

Chcę utworzyć stronicowanie dla systemu przesyłania wiadomości, w którym pierwsza wyświetlana strona zawiera najstarsze wiadomości, a kolejne strony zawierają nowsze wiadomości.Odwróć paginację z kaminari

Na przykład jeśli normalne stronicowanie do {a,b,c,d,e,f,g,h,i} z 3 na stronie:

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

Następnie odwrotnej stronicowanie to:

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

Planuje Dołączenie kartek, wynik jest taki sam jako normalną paginację, zaczynając od ostatniej strony.

Czy jest to możliwe z kaminari?

+0

Dlaczego po prostu nie powtarzasz odwróconego zestawu danych? 'YourModel.order (" created_at ASC "). Strona"? – thomasfedb

Odpowiedz

0

Tak, ale metoda, którą wymyśliłem, nie jest całkiem ładna. Skutecznie, trzeba ustawić własną kolejność:

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

Problem z tym podejściem jest dwojaki:

Pierwsza odwrotna! call rozstrzyga zakres do tablicy i wykonuje zapytanie, niwecząc niektóre niesamowite aspekty kaminari używając zakresów AR.

Po drugie, podobnie jak w przypadku odwrotnej paginacji, przesunięcie będzie się przesuwać, co oznacza, że ​​pomiędzy dwoma kolejnymi połączeniami można wysłać dokładnie 3 nowe wiadomości i odzyskać dokładnie te same dane. Ten problem jest związany z odwrotną paginacją.

Alternatywnym rozwiązaniem byłoby przesłuchać „ostatnie” numer strony i zwiększyć swój numer strony w dół w kierunku 1.

+0

Coś jak: 'pages = Message.count% 3; Message.page (pages - i) .per (3) .order ("created_at DESC") '? – Trompa

+0

Z wyjątkiem 'order (" created_at DESC ")' powinno być 'order (" created_at ASC ")' jeśli zamierzasz korzystać z tego podejścia. –

2

Istnieje dobry przykład repo na Github o nazwie reverse_kaminari na github. Sugeruje implementację wzdłuż tych linii (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 

Wszystkie kredyty otrzymują do Andrew Djoga. On również hostował aplikację jako a working demo.

1

Kaminary.paginate_array nie generuje zapytania z offsetem i limitem. Ze względu na optymalizację nie powinieneś tego używać.

Zamiast tego można to zrobić:

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

Gdzie query_for_message oznacza każde zapytanie za pomocą którego można pobierać rekordy paginacji. Na przykład mogą to być wszystkie wiadomości danej rozmowy.

Teraz w pliku widoku wystarczy wyświetlić numer @messages w odwrotnej kolejności. Na przykład:

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