例如,我想做一个daily pick
,所以我需要选择一些随机对象。
所以我这样做@posts = Posts.all.shuffle
。
但是,我不希望每次用户进入页面时都会更改。相反,我只需要每天改变它(即daily pick
)
我该怎么做?
答案 0 :(得分:1)
有多种方法可以做到这一点,最好取决于您的特定应用。我不知道你的应用程序,我可能会做以下事情:
配置Rails缓存以使用memcached或redis或支持基于密钥的过期的任何内容。
在app / models / post.rb中:
class Post < ActiveRecord::Base
def self.daily_picks
Rails.cache.fetch('post_daily_picks', expires_in: 1.day) do
self.all.shuffle.limit(5)
end
end
end
现在,您只需在代码中的其他位置使用Post.daily_picks
即可访问这5个随机选择的选项。密钥将在1天后到期,此时它将被重新生成。
其他一些想法:
如果你有任何不错的帖子,那么 self.all.shuffle.limit(5)
可以获得非常昂贵的数据库查询。您可能需要考虑使用帖子总数,随机数和SQL偏移量来做一些奇特的事情。这将意味着5个查询而不是一个,但你不会只返回所有帖子来选择5.例如:像这样:
5.times.map { self.offset(rand(self.count)).first }
如果您无法设置memcached / redis并且必须使用基于文件的缓存,那就没关系。您只需要添加一个cron作业,每天删除一次缓存文件。
请注意,以上内容会获取5个帖子并将其缓存一天。如果这些帖子全天都在变化,则缓存版本将不会反映出这一点(即将使用旧帖子标题)。你可能想要这样做。这只会缓存5个帖子ID,然后每次都会获取它们。
class Post < ActiveRecord::Base
def self.daily_picks
daily_pick_ids = Rails.cache.fetch('post_daily_picks', expires_in: 1.day) do
self.pluck(:id).shuffle.limit(5)
end
self.where(ids: daily_pick_ids)
end
end
最后,考虑一下thundering hurd problem。假设您有使用每日选择的数千个活动请求。缓存过期了。 1000人刷新该页面。由于竞争条件,一个好的数字将执行该SQL。我觉得这对此没什么大不了的,但值得记住。
答案 1 :(得分:0)
我相信菲利普的想法很棒但是当他提到雷鸣般的问题时,我想知道其他一些方法。这就是我想到的:
time = Time.now
@posts = Posts.all
并选择一天你可以使用的帖子:
Posts.find(time.yday%@posts.size)
你应该能够开发它来挑选更多。