加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 用于收集的低级缓存

发布时间:2020-12-17 03:18:09 所属栏目:百科 来源:网络整理
导读:我想在我的Rails应用程序中使用Redis进行一些低级缓存. 在控制器中,我通常使用它来获取所有书籍: class BooksController ApplicationController def index @books = Book.order(:title) endend 视图迭代了这个: ul - @books.each do |book| li= "#{book.ti
我想在我的Rails应用程序中使用Redis进行一些低级缓存.
在控制器中,我通常使用它来获取所有书籍:

class BooksController < ApplicationController
  def index
    @books = Book.order(:title)
  end
end

视图迭代了这个:

<ul>
  - @books.each do |book|
    <li>= "#{book.title} - #{book.author}"</li>
</ul>

现在我想要完全相同的结果,然后缓存.我有Redis设置并运行.所以我应该在控制器中使用cached_books方法,如下所示:

@books = Book.cached_books.order(:title)

保持视图原样,或者在视图中使用book.cached_title和book.cached_author并保持控制器原样?

如何在Book模型中使用cached_books方法?

class Book < ActiveRecord::Base
  ...

  def cached_books
    Rails.cache.fetch([self,"books"]) { books.to_a }
  end
end

为了简单起见,我暂时忽略了过期策略,但显然他们需要在那里.

解决方法

So should I use a cached_books method in the controller like this:

是的你可以.虽然有一些问题你必须要注意.
书是ActiveRecord.当你调用Book.something(例如Book.all,或者甚至是Book.order(:title)时,它会返回一个ActiveRecord :: Relation,它基本上是Books数组的包装器(这个包装器可以防止触发不必要的查询,提高性能) ).

您无法在Redis中保存查询的整个结果.比如,您可以使用模型属性保存哈希数组的JSON字符串,例如

[{
  id: 1,title: 'How to make a sandwich",author: 'Mr. cooker'
},{
  id: 2,title: 'London's Bridge',author: 'Fergie'
}]

然后你可以将这个东西“解密”到数组之后.就像是

def cached_books(key)
  # I suggest you to native wrapper
  if result = $redis.hget 'books_cache',key
    result.map do { |x| Book.new(x) }
  end
end

而且,在将属性放入缓存之前,您必须序列化属性.

好的,现在你有了可以在视图中使用相同数据迭代的集合,尽管你不能在缓存集合上调用顺序,因为它是一个普通数组(你可以调用sort,但想法是缓存已排序的数据) ).

嗯……值得吗?实际上,不是真的.如果你需要缓存这篇文章 – 最好的方法是缓存一个渲染的页面,而不是一个查询结果.

你应该使用cached_title和cached_author – 这是个好问题.首先,它取决于cached_title可能是什么.如果它是一个字符串 – 没有什么可以缓存.您可以获得Book to DB请求,或者从缓存中获取Book – 以任何方式将标题显示在其中,因为它是一种简单类型.但让我们看一下作者.最有可能的是它与另一个模型作者的关系,这是缓存非常适合的地方.你可以在书中重新定义作者方法(或者定义新的并避免将来Rails在复杂查询中可能产生的令人讨厌的影响)并查看是否有缓存.如果是,请返回缓存.如果不是 – 查询数据库,将结果保存到缓存并返回它.

def author
  Rails.cache.fetch("#{author_id}/info",expires_in: 12.hours) do
    # block executed if cache is not founded
    # it's better to alias original method and call it here
    #instead of directly Author.find call though
    Author.find(author_id) 
  end
end

或者不太方便,但更“安全”:

def cached_author
  Rails.cache.fetch("#{author_id}/info",expires_in: 12.hours) do
    author
  end
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读