Rails 5.2.1 - 模型和片段缓存
Rails 5.2.1 - Model & Fragment Caching
我正在尝试在 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
观看次数
app/views/languages/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" = AND "languages"."approved" = [["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)
为什么每次请求时我仍然看到数据库查询?
这里似乎发生的事情是您在 加载记录之前缓存关系 ,因此它仍然必须在可以使用之前实际加载它们(使用我的广告模型,因为它在那里并且方便在 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"
我之前很接近,但现在已经成功实现了缓存。上面的答案很受欢迎,但不是我想要的,这是我当前的设置。
我本应将语言模型查询移动到模型中,却在助手模块中调用它。
型号
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)
我正在尝试在 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
观看次数
app/views/languages/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" = AND "languages"."approved" = [["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)
为什么每次请求时我仍然看到数据库查询?
这里似乎发生的事情是您在 加载记录之前缓存关系 ,因此它仍然必须在可以使用之前实际加载它们(使用我的广告模型,因为它在那里并且方便在 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"
我之前很接近,但现在已经成功实现了缓存。上面的答案很受欢迎,但不是我想要的,这是我当前的设置。
我本应将语言模型查询移动到模型中,却在助手模块中调用它。
型号
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)