分页最佳实践Ruby

时间:2013-07-19 03:40:06

标签: ruby-on-rails ruby pagination kaminari

所以我正在开发一个rails应用程序,我正在研究分页Feed。当我这样做时,我想知道我是否正确地做到了这一点,因为我的加载时间超过了1500毫秒。我的代码是:

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

我对此有几个问题:

  1. 我应该分页Story.feed,还是有某种方法 只返回一些我需要的故事?
  2. 这个加载时间是否正常?
  3. 我可以采取哪些其他措施来优化此
  4. (另外,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 个答案:

答案 0 :(得分:0)

我怀疑当你在Kaminari.paginate_array上调用ActiveRecord::Relation时,它会导致整个结果集从数据库中获取并加载到内存中,类似于调用Model.all.to_a

为了避免这种情况,我首先找到一种方法将Story.feed转换为范围,而不是类方法。从表面上看,它们看起来是一样的 - 差异是微妙而深刻的。请参阅Active Record scopes vs class methods

接下来,放弃paginate_array支持链Kaminari的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中插入正确的LIMITOFFSET子句,从而减少返回到只需要显示的结果集的大小,如反对返回每个匹配的记录。

答案 1 :(得分:0)

问题是您从数组中获取db的所有提要,这需要很长时间。

我建议您使用any_of查询from 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是什么,而是在这一刻得到它们。

总结一下:创建一个独特的分页数据库查询。

答案 2 :(得分:-1)

我认为Will Paginate会帮助你 - &gt; mislav/will_paginate。 从那里你可以简单地给你的控制器动作.per_page(20)例如在20个对象之后(你可以定义对象,参见wiki)会有分页