Есть много случаев, когда will_paginate выполняет действительно ужасную работу по вычислению количества записей, особенно если в него включены объединения, которые приводят в замешательство генератор SQL count.
Если все, что вам нужно, это простой предыдущий / предыдущий метод, то все, что вам нужно сделать, это попытаться получить N + 1 записей из базы данных, и если вы получите только N или меньше, чем на последней странице.
Например:
per_page = 10
page = 2
@entries = Thing.with_some_scope.find(:all, :limit => per_page + 1, :offset => (page - 1) * per_page)
@next_page = @entries.slice!(per_page, 1)
@prev_page = page > 1
Вы можете легко инкапсулировать это в некоторый модуль, который может быть включен в различные модели, которые требуют этого, или сделать расширение контроллера.
Я обнаружил, что это работает значительно лучше, чем метод will_paginate по умолчанию.
Единственная проблема с производительностью - это ограничение MySQL, которое может быть проблемой в зависимости от размера ваших таблиц.
По какой-то причине время, необходимое для выполнения запроса с небольшим LIMIT в MySQL, пропорционально OFFSET. По сути, ядро базы данных считывает все строки, ведущие к конкретному значению смещения, а затем возвращает следующие строки числа LIMIT, не пропуская вперед, как вы ожидаете.
Для больших наборов данных, где значения OFFSET находятся в диапазоне от 100 000 с плюсом, производительность может значительно снизиться. Это проявится в том, что загрузка страницы 1 очень быстрая, страница 1000 несколько медленная, а страница 2000 очень медленная.