2013-07-19 4 views
0

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

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

ответ

0

Я думаю, что отформатирую помогут вам здесь. ->mislav/will_paginate Оттуда вы можете просто дать свое действие контроллера .per_page (20), например, и после того, как 20 объектов (вы можете определить объективистский TS, см вики) будет PAGINATION

0

Я подозреваю, что, когда вы звоните Kaminari.paginate_array на ActiveRecord::Relation, это приводит к тому, весь набор результатов быть извлечена из БД и загружаются в память аналогично вызову Model.all.to_a.

Чтобы избежать этого, я бы сначала нашел способ превратить Story.feed в область видимости, а не метод класса. Поверхностно они кажутся одинаковыми - различия тонкие, но глубокие. См. Active Record scopes vs class methods.

Далее, канава paginate_array в пользу цепи Kaminari's 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, что уменьшает размер набора результатов, возвращаемых только на то, что должно отображаться, в отличие от возврата каждой соответствующей записи.

+0

Это возвращает только избранные истории за последние 3 дня. Мне нужна функциональность, чтобы рассказы о лучших статьях были отличными от истории, независимо от даты, а затем ниже, чем остальные истории, отсортированные по дате created_at. –

+0

Как я уже сказал, это упрощенная версия. Дело в том, чтобы использовать 'per(). Page()' вместо 'concat' и' paginate_array' (выборку каждой соответствующей записи). Вы должны быть тем, кто переписывает весь составный запрос как область (я просто предполагаю, что это возможно, я могу ошибаться). –

0

Проблема в том, что вы получаете все каналы из db в массиве, и это занимает много времени.

Предлагаю вам использовать запрос any_offrom this great gem.

Оттуда, сделайте следующее:

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, но получить их в данный момент.

Подводя итог: идея s создать уникальный запрос с разбивкой по страницам.

+0

Я получаю эту ошибку '' 'undefined method' inject 'для # '' ' –