Обратное разбиение на страницы с каминари
Я хочу создать разбивку на страницы для системы обмена сообщениями, в которой первая страница содержит самые старые сообщения, а последующие страницы содержат более новые сообщения.
Например, если обычная разбивка на страницы для {a,b,c,d,e,f,g,h,i}
с 3 на страницу:
{a,b,c}, {d,e,f}, {g,h,i}
Тогда обратная разбивка на страницы будет следующей:
{g,h,i}, {d,e,f}, {a,b,c}
Я планирую добавлять страницы так, чтобы результат был таким же, как и обычная разбивка на страницы, только начиная с последней страницы.
Возможно ли это с помощью kaminari
?
Ответы
Ответ 1
Там хороший пример репо на Github, называемый reverse_kaminari в github. Он предлагает реализацию в этих строках (Источник).
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
Все кредиты идут в Andrew Djoga. Он также разместил приложение как рабочую демонстрацию.
Ответ 2
Одним из способов решения этой проблемы будет следующий:
Обратное разбиение на страницы с каминари?
Он не выглядит очень чистым и оптимальным, но он работает:)
Ответ 3
Kaminary.paginate_array
не создает запрос со смещением и лимитом. По соображениям оптимизации вы не должны использовать это.
Вместо этого вы можете сделать это:
@messages = query_for_message.order('created_at DESC').page(params[:page]).per(3)
Где query_for_message
обозначает любой запрос, который вы используете для извлечения записей для разбивки на страницы. Например, это могут быть все сообщения определенного разговора.
Теперь в файле просмотра вам просто нужно отобразить @messages
в обратном порядке. Например:
<%= render :collection => @messages.reverse, :partial => 'message' %>
<%= paginate @messages %>
Ответ 4
Да, но метод, который я придумал, не совсем хорош. Фактически, вы должны установить свой собственный порядок:
Message.page(1).per(3).order("created_at DESC").reverse!
Проблема с этим подходом двоякая:
Сначала обратное! вызов разрешает область для массива и выполняет запрос, устраняя некоторые из удивительных аспектов kaminari, использующих области AR.
Во-вторых, как и любая обратная разбивка на страницы, ваше смещение будет двигаться, что означает, что между двумя повторными вызовами вы можете отправить ровно 3 новых сообщения, и вы получите точные данные обратно. Эта проблема присуща обратной разбивке на страницы.
Альтернативным подходом было бы опросить "последний" номер страницы и увеличить ваш номер страницы до 1.