Rails 3: Куда поместить вызов Rails.cache.fetch для обогрева кеша?

Предположим, вы хотите выполнить низкоуровневое кэширование в Rails (например, с помощью memcached) и хотите, чтобы где-то в вашем приложении был только 1 вызов, например...

Rails.cache.fetch('books', expires_in: 1.day) do
  Book.offset(offset)
      .limit(limit)
      .select('title, author, number_of_pages')
      .all
end

... чтобы разогреть кеш при загрузке приложения, поэтому вы можете просто использовать простой вызов, например...

Rails.cache.read('books')

...в любом месте и несколько раз в приложении (в представлениях, контроллерах, помощниках...) для доступа к этой коллекции "книг".

Куда нужно поместить первоначальный вызов «fetch», чтобы он работал?


person TomDogg    schedule 07.05.2013    source источник
comment
Зачем это делать при загрузке приложения? Если срок действия вашего кеша истекает через 1 день, не лучше ли запускать его один раз в день? Я бы обернул его в задачу rake и запустил с cron.   -  person spike    schedule 07.05.2013
comment
@spike. Предположим, что значение :expires_in также может быть намного длиннее. (И я решил сделать это при загрузке приложения, потому что я бы использовал более короткий Rails.cache.read везде.)   -  person TomDogg    schedule 07.05.2013


Ответы (2)


После вашего комментария хочу прояснить пару вещей.

Вы всегда должны использовать fetch, если вам нужен результат, чтобы вернуться. Оберните вызов в методе класса внутри Book для быстрого доступа:

class Book
  def self.cached_books 
    Rails.cache.fetch < ... > 
  end
end

У вас может быть другой метод принудительного воссоздания кеша:

def self.write_book_cache
     Rails.cache.write < ... > 
   end
end

Затем в вашем инициализаторе или в задаче rake вы можете просто сделать:

Book.write_book_cache

Это кажется мне более удобным для сопровождения, сохраняя при этом краткий вызов кеша в остальной части вашего кода.

person spike    schedule 07.05.2013
comment
ОБЯЗАТЕЛЬНО ли всегда использовать выборку? Я имею в виду, даже если вы знаете, что каким-то образом уже заполнили кеш, например, при загрузке приложения? - person TomDogg; 07.05.2013
comment
Если в memcached закончится место, старые ключи будут удалены. Вы не должны предполагать, что ваш кеш наверняка существует только потому, что вы что-то туда поместили. - person spike; 07.05.2013
comment
(PS: Если я не ошибаюсь, Book.write_book_cache будет находиться в блоке config.after_initialize do... end в application.rb, поэтому у вас загружены модели, в отличие от инициализатора.) - person TomDogg; 07.05.2013
comment
Для дальнейшего улучшения: 2 метода выше могут стать 1, используя первый и просто установив force: true - person TomDogg; 07.05.2013
comment
Это была моя первая мысль, но я на самом деле думаю, что два метода понятнее, чем один общий cached_books, который принимает аргумент, который делает его разрушительным. - person spike; 07.05.2013

Моей первой мыслью было бы поместить его в инициализатор - возможно, специально для этой цели (/config/initializers/init_cache.rb или что-то подобное).

Он должен выполняться автоматически (в силу того, что он находится в папке инициализаторов) при запуске приложения.

person MrTheWalrus    schedule 07.05.2013
comment
Проблема с этим решением заключается в том, что модели должны быть загружены до того, как этот кеш может быть заполнен. - person TomDogg; 07.05.2013