Rails 5.2.1 — Кэширование моделей и фрагментов

Я пытаюсь настроить кэширование моделей и фрагментов в Rails 5.2.1.

Я добился успеха с кэшированием фрагментов, но я все еще вижу запросы к базе данных после реализации кэширования модели для моей модели.

Я включил кэширование разработки

$ rails dev:cache

Помощник по модели

module LanguagesHelper
  def approved_languages
    Rails.cache.fetch("approved_languages") { Languages.is_active.is_approved }
  end
end

Контроллер

class LanguagesController < ApplicationController
  include LanguagesHelper

  def index
    @languages = approved_languages
  end
end

Просмотры

приложение/представления/языки/index.html.erb

<%= render partial: 'languages/language', collection: @languages, cached: true %>

app/views/languages/_language.html.erb

<% cache language do %>
  <%= language.name %>
<% end %>

Консоль

Started GET "/languages" for 127.0.0.1 at 2018-08-21 14:13:29 -0400
Processing by LanguagesController#index as HTML
  Rendering languages/index.html.erb within layouts/application
  Language Load (1.2ms)  SELECT "languages".* FROM "languages" WHERE "languages"."deleted" = $1 AND "languages"."approved" = $2  [["deleted", false], ["approved", true]]
  ↳ app/views/languages/index.html.erb:4
  Rendered collection of languages/_language.html.erb [1 / 1 cache hits] (3.0ms)
  Rendered languages/index.html.erb within layouts/application (10.9ms)
Completed 200 OK in 50ms (Views: 46.2ms | ActiveRecord: 1.2ms)

Почему я все еще вижу запросы к базе данных с каждым запросом?


person Alexander Smith    schedule 21.08.2018    source источник


Ответы (2)


Кажется, что здесь происходит то, что вы кэшируете отношение до, когда оно загружает записи, и поэтому оно все еще должно фактически загрузить их, прежде чем его можно будет использовать (используя мою рекламную модель, потому что она там есть). и удобно для тестирования в irb):

ads = Ad.all;nil # no query here, this is what I think you're caching
# this next line is where the query is run, (this would be
# equivalent to your render line)
ads.each { ... } 
#  Ad Load (0.1ms)  SELECT "ads".* FROM "ads"

вместо этого вы можете попробовать заставить активную запись загружать отношение, прежде чем кэшировать его, и посмотреть, поможет ли это. Это можно сделать с помощью load:

ads = Ad.all.load;nil # query is now run here
#  Ad Load (0.1ms)  SELECT "ads".* FROM "ads"
ads.each { ... } # and not run here

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

ads = Rails.cache.fetch("test load") { Ad.all.load };nil # query
#  Ad Load (0.9ms)  SELECT "ads".* FROM "ads"
ads = Rails.cache.fetch("test load") { Ad.all.load };nil # no query
ads.each {  } # no query
ads = Rails.cache.fetch("test without load") { Ad.all };nil # no query
ads.each { };nil # query
#  Ad Load (0.1ms)  SELECT "ads".* FROM "ads"
ads = Rails.cache.fetch("test without load") { Ad.all };nil # no query
ads.each { };nil # query
#  Ad Load (0.1ms)  SELECT "ads".* FROM "ads"
person Simple Lime    schedule 21.08.2018

Раньше я был близок, но теперь успешно внедрил кеширование. Приведенный выше ответ был оценен, но это не то, что я искал, это моя текущая настройка.

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

Модель

after_save :clear_cache
after_destroy :clear_cache

def clear_language_cache
  Rails.cache.delete('Language.active.approved')
end

def self.active_approved
  Rails.cache.fetch('Language.active.approved') { is_active.is_approved.order(created_at: :desc).to_a }
end

Контроллер

class LanguagesController < ApplicationController
  def index
    @languages = Language.active_approved
  end
end

Консоль

Started GET "/languages" for 127.0.0.1 at 2018-08-22 18:13:21 -0400
Processing by LanguagesController#index as HTML
  Rendering languages/index.html.erb within layouts/application
  Rendered collection of languages/_language.html.erb [1 / 1 cache hits] (11.0ms)
  Rendered languages/index.html.erb within layouts/application (15.9ms)
Completed 200 OK in 68ms (Views: 45.5ms | ActiveRecord: 5.8ms)
person Alexander Smith    schedule 22.08.2018