Нумерация страниц Ruby
Поэтому я занимаюсь разработкой приложения для рельсов и работаю над разбиением на страницы. Пока я делал это, я задавался вопросом, правильно ли я это делал, потому что время моей загрузки превышало 1500 мс. Мой код был:
stories = Story.feed
@stories = Kaminari.paginate_array(stories).page(params[:page]).per(params[:pageSize])
У меня есть несколько вопросов по этому поводу:
- Должен ли я быть нумерацией страниц
Story.feed
, или есть какой-то метод, который возвращает только некоторые истории, которые мне нужны? - Это время загрузки нормально?
- Какие другие вещи я могу сделать, чтобы оптимизировать это
(Кроме того, Story.feed возвращает массив объектов истории. Код для этого здесь:
def self.feed
rawStories = Story.includes([:likes, :viewers, :user, :storyblocks]).all
newFeaturedStories = rawStories.where(:featured => true).where(:updated_at.gte => (Date.today - 3)).desc(:created_at).entries
normalStories = rawStories.not_in(:featured => true, :or => [:updated_at.gte => (Date.today - 3)]).desc(:created_at).entries
newFeaturedStories.entries.concat(normalStories.entries)
end
Я использую mongoid и mongodb
3 ответа
Проблема в том, что вы получаете все каналы из базы данных в массиве, и это занимает много времени.
Я предлагаю вам использовать any_of
запрос из этого великого камня.
Оттуда сделайте:
def self.feed_stories
newFeaturedStories = Story.where(:featured => true).where(:updated_at.gte => (Date.today - 3.days))
normalStories = Story.not_in(:featured => true, :or => [:updated_at.gte => (Date.today - 3.days)])
Story.includes([:likes, :viewers, :user, :storyblocks]).any_of(newFeaturedStories, normalStories).desc(:created_at)
end
Тогда разбейте на страницы это:
selected_stories = Story.feed_stories.per(page_size).page(page)
Не понимаю, каковы ваши entries
но получите их в этот момент.
Подводя итог: идея состоит в том, чтобы сделать уникальный постраничный запрос БД.
Я подозреваю, что когда вы звоните Kaminari.paginate_array
на ActiveRecord::Relation
, это приводит к тому, что весь набор результатов извлекается из БД и загружается в память, аналогично вызову Model.all.to_a
,
Чтобы избежать этого, я бы сначала нашел способ повернуть Story.feed
в область, а не метод класса. Внешне они кажутся одинаковыми - различия тонкие, но глубокие. См. Области Active Record против методов класса.
Далее канава paginate_array
в пользу цепочки каминари page()
а также per()
прицелы.
Например (ваша упрощенная версия):
class Article < ActiveRecord::Base
scope :featured, -> { where(featured: true) }
scope :last_3_days, -> {
where(:updated_at.gte => (Date.today - 3)).desc(:created_at)
}
scope :feed, -> { featured.last_3_days }
А потом просто разберитесь на страницы:
Article.feed.per(page_size).page(page)
Самым большим преимуществом этого является то, что Kaminari может подключиться к сгенерированному SQL, вставляя правильный LIMIT
а также OFFSET
тем самым уменьшая размер результирующего набора, возвращая только то, что необходимо отобразить, а не возвращая каждую соответствующую запись.
Я думаю, Уилл Пагинат поможет вам здесь -> https://github.com/mislav/will_paginate. Оттуда вы можете просто указать действие вашего контроллера.per_page(20), например, и после 20 объектов (вы можете определить объекты, см. Вики) произойдет разбиение на страницы.