有没有办法在Rails中使用Memcached进行片段缓存?
我试图在每个元素的基础上将内容插入我的页面的头部,所以我希望能够在部分指定这样的内容:
# _partial.html.erb
<%= content_for :style %>
.element {
background-color: red;
}
<% end %>
Run Code Online (Sandbox Code Playgroud)
并将其放在我的页面的头部:
# application.html.erb
<head>
<style>
<%= content_for(:style) %>
</style>
</head>
Run Code Online (Sandbox Code Playgroud)
但是元素部分是片段缓存的,content_for在缓存中被忽略。
它在 Rails 文档中声明content_for不会用于片段缓存的工作元素:
WARNING: content_for is ignored in caches. So you shouldn't use it for elements that will be fragment cached.
http://api.rubyonrails.org/classes/ActionView/Helpers/CaptureHelper.html#method-i-content_for
目前有没有办法content_for在 Rails 5.1 上使用片段缓存?似乎已经有一段时间没有人真正触及这个问题了。有谁知道是否有原因?
这里有一些较旧的提及:
是否有使用 caches_action 和 :layout => false 忽略 content_for 块的解决方法?
https://gist.github.com/stackng/891895
https://rails.lighthouseapp.com/projects/8994/tickets/3409-content_for-and-fragment-caching
caching ruby-on-rails fragment-caching content-for ruby-on-rails-5.1
我正在努力将片段缓存添加到已登录和匿名用户的Rails 3站点,并且需要根据整个站点中显示的内容何时更新来控制页面的某些部分何时到期.中途,我发现memcached不支持expire_fragment的regexp,所以现在我正在寻找方法.
对于匿名用户来说,这不是一个大问题.我创建缓存键,例如'frontpage-new-shows'或'schedule-weekly-forecast-10/24/10',并在Show模型中创建新条目时使用,或者在下周播出时播放通过扫地机进行修改.这很好用.
我的问题是登录的用户.他们每个人都有自己的自定义日程安排,所以我的密钥看起来像'schedule-user-jschuur-10/10/24',jschuur是帐户的用户名.我理解,使用基于日期的约定,它们会自然过期,但我还希望在当天(或周)的日程安排中显示相关更改的那一天显式过期缓存日程表的所有片段.
事实证明,memcached不能做我需要的那种通配符到期(schedule-user - .* - 10/10/24).这意味着我需要某种解决方案来存储在memcached中的中央查找键中发布的所有密钥,或者让Rails/Ruby在内部根据我发送给memcached的密钥在内部执行此操作.
我假设前者是更好的解决方案.我的问题是,我该如何以最有效的方式做到这一点,所以我不会把所有的时间都打破,而不是再次击中数据库.我可以在memcached中存储数组或散列,检索整个事情,如果匹配则循环,删除它们并将散列存储回来.听起来它可能适用于几百甚至一千个用户,但这真的是最好的方法吗?
有人已经解决了这个问题并发布了解决方案吗?
需要考虑的一件事是,我的几乎所有缓存都是在视图中使用语句完成的,面向ActiveRelations准备好的尚未触发的查询,如下所示:
<% if current_user %>
<% if current_user.saved_shows_count %>
<% cache "schedule-user-#{current_user.username}-#{(Time.now + 3.hours).to_date.end_of_week.strftime('%D')}" do %>
<% if @shows.any? %>
<%= render :partial => "schedule/schedule", :locals => { :shows => @shows } %>
<% end %>
<% end %>
...
Run Code Online (Sandbox Code Playgroud)
该网站托管在Heroku上,我使用dalli gem作为客户端.
我正在尝试将缓存碎片化为我网站的静态部分,但它似乎根本不起作用.我已经设置了config/application.rb以下内容:
config.action_controller.perform_caching = true
config.cache_store = :dalli_store
Run Code Online (Sandbox Code Playgroud)
在我看来,我有这个:
<% cache 'cache_key' do %>
<!-- cached markup -->
<% end %>
Run Code Online (Sandbox Code Playgroud)
我在日志中没有看到任何关于将片段保存到缓存或在后续页面加载时检索它的内容.我也尝试使用默认的Rails :file_store缓存.我知道缓存存储正在工作,因为使用Rails.cache.fetch正常.
我怎样才能让它发挥作用?
我想用扫地机过期碎片.执行sweeper回调,但对expire_fragment的调用什么都不做,因为(我假设)cache_configured?返回零.配置缓存并在我的模板中创建和使用片段(在日志中验证它).我究竟做错了什么?
application.rb中
config.cache_store = :mem_cache_store, "XXX.XXX.XXX.XXX", { # I use a real IP
:compress => true,
:namespace => "#{Rails.env}_r3"
}
config.active_record.observers = [:auction_sweeper, :address_sweeper]
Run Code Online (Sandbox Code Playgroud)
production.rb
config.action_controller.perform_caching = true
Run Code Online (Sandbox Code Playgroud)
auction_sweeper.rb
class AuctionSweeper < ActionController::Caching::Sweeper
observe Auction
def after_create(auction)
Rails.logger.info "AuctionSweeper.expire_details #{auction.id} #{cache_configured?.inspect}=#{perform_caching.inspect}&&#{cache_store.inspect}"
expire_fragment("auction/#{auction.reference_sid}")
end
end
Run Code Online (Sandbox Code Playgroud)
在日志文件中,cache_configured?是nil,perform_caching和cache_store也是如此.
AuctionSweeper.expire_details 12732 nil=nil&&nil
Run Code Online (Sandbox Code Playgroud)
所以我假设,我的片段没有过期,因为expire_fragment的代码读取:
文件actionpack/lib/action_controller/caching/fragments.rb,第87行
87: def expire_fragment(key, options = nil)
88: return unless cache_configured?
Run Code Online (Sandbox Code Playgroud) configuration memcached caching fragment-caching ruby-on-rails-3
我有一个用户个人资料页面,其侧边栏的用户统计信息与Stack Overflow个人资料页面不同(例如,总访问次数,徽章数量).
麻烦的是,目前我正在访问数据库并使用每个请求计算这些统计数据.我可以实现片段缓存来减少这个,但有没有更好的方法来处理这类事情?
将聚合的摘要数据存储在数据库中似乎可能会导致问题(即不一致).
当我有2个视图片段缓存相同的查询但是以不同方式显示它们时,只有一个片段,它们都以相同的方式显示它们.有没有办法解决?例如...
#views/posts/list
- cache(@posts) do
- for p in @posts
= p.title
#views/posts/list_with_images
- cache(@posts) do
- for p in @posts
= p.title
= p.content
= image_tag(p.image_url)
#controllers/posts_controller
def list
...
@posts = Post.all
end
def list_with_images
...
@posts = Post.all
end
Run Code Online (Sandbox Code Playgroud)