Обратное разбиение на страницы с каминари

Я хочу создать разбивку на страницы для системы обмена сообщениями, в которой первая страница содержит самые старые сообщения, а последующие страницы содержат более новые сообщения.

Например, если обычная разбивка на страницы для {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. Он также разместил приложение как рабочую демонстрацию.

Ответ 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.