Нумерация страниц Ruby

Поэтому я занимаюсь разработкой приложения для рельсов и работаю над разбиением на страницы. Пока я делал это, я задавался вопросом, правильно ли я это делал, потому что время моей загрузки превышало 1500 мс. Мой код был:

stories = Story.feed
@stories = Kaminari.paginate_array(stories).page(params[:page]).per(params[:pageSize])

У меня есть несколько вопросов по этому поводу:

  1. Должен ли я быть нумерацией страниц Story.feed, или есть какой-то метод, который возвращает только некоторые истории, которые мне нужны?
  2. Это время загрузки нормально?
  3. Какие другие вещи я могу сделать, чтобы оптимизировать это

(Кроме того, 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 объектов (вы можете определить объекты, см. Вики) произойдет разбиение на страницы.

Другие вопросы по тегам