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 books (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