ruby on rails - Low level caching for collection -
i want use redis low level caching in rails app. in controller books:
class bookscontroller < applicationcontroller def index @books = book.order(:title) end end
and view iterates on this:
<ul> - @books.each |book| <li>= "#{book.title} - #{book.author}"</li> </ul>
now want exact same result cached. have redis setup , running. should use cached_books
method in controller this:
@books = book.cached_books.order(:title)
and leave view is, or use book.cached_title
, book.cached_author
in view , leave controller is?
and how cached_books
method in book
model?
class book < activerecord::base ... def cached_books rails.cache.fetch([self, "books"]) { books.to_a } end end
for simplicity sake leave out expire strategies now, need there.
so should use cached_books method in controller this:
yes, can. although there's gotchas have aware of. book
activerecord
. when call book.something
(e.g. book.all
, or book.order(:title)
returns activerecord::relation
, wrapper array of book
s (this wrapper prevents of firing unnecessary queries, boosting perfomance).
you can't save whole result of query in redis. say, can save json string of array of hashes model attributes, e.g.
[{ id: 1, title: 'how make sandwich", author: 'mr. cooker' }, { id: 2, title: 'london's bridge', author: 'fergie' }]
and can 'decrypt' thing array after. like
def cached_books(key) # suggest native wrapper if result = $redis.hget 'books_cache', key result.map { |x| book.new(x) } end end
and also, have serialise attributes before putting them cache.
ok, have collections can iterated in view same data, although can't call order
on cached collection, plain array (you may call sort
, idea cache already sorted data).
well... worth it? actually, not really. if need cache piece – probably, best way cache rendered page, not query result.
should use cached_title
, cached_author
– that's question. first of all, depends on cached_title
may be. if string – there's nothing can cache. book
through db request, or book
cache – in way title
presented in it, simple type. let's closer author
. going relation model author
, place cache suits great. can re-define author
method inside book (or define new , avoid nasty effects rails may have in complex queries in future) , see if there's cache. if yes, return cache. if not – query db, save result cache , return it.
def author rails.cache.fetch("#{author_id}/info", expires_in: 12.hours) # block executed if cache not founded # it's better alias original method , call here #instead of directly author.find call though author.find(author_id) end end
or less convenient, more "safe":
def cached_author rails.cache.fetch("#{author_id}/info", expires_in: 12.hours) author end end
Comments
Post a Comment