Loading...
Loading...
Compare original and translation side by side
fresh_whentouch: trueRails.cache.fetchfresh_whentouch: trueRails.cache.fetch| Store | Use Case |
|---|---|
| Development |
| Production (Rails 8 default) |
| Production (if Redis available) |
| Testing |
undefined| 存储类型 | 使用场景 |
|---|---|
| 开发环境 |
| 生产环境(Rails 8默认) |
| 生产环境(若有Redis可用) |
| 测试环境 |
undefined
Enable caching in development:
```bash
bin/rails dev:cache
在开发环境中启用缓存:
```bash
bin/rails dev:cacheclass EventsController < ApplicationController
def show
@event = current_account.events.find(params[:id])
fresh_when @event
end
def index
@events = current_account.events.recent
fresh_when @events
end
endclass EventsController < ApplicationController
def show
@event = current_account.events.find(params[:id])
fresh_when @event
end
def index
@events = current_account.events.recent
fresh_when @events
end
enddef show
@event = current_account.events.find(params[:id])
fresh_when [@event, Current.user]
enddef show
@event = current_account.events.find(params[:id])
fresh_when [@event, Current.user]
endclass Api::EventsController < Api::BaseController
def show
@event = current_account.events.find(params[:id])
if stale?(@event)
render json: @event
end
end
endclass Api::EventsController < Api::BaseController
def show
@event = current_account.events.find(params[:id])
if stale?(@event)
render json: @event
end
end
end<%# app/views/events/_event.html.erb %>
<% cache event do %>
<article class="event-card">
<h3><%= event.name %></h3>
<p><%= event.description %></p>
<time><%= l(event.event_date, format: :long) %></time>
</article>
<% end %><%# app/views/events/_event.html.erb %>
<% cache event do %>
<article class="event-card">
<h3><%= event.name %></h3>
<p><%= event.description %></p>
<time><%= l(event.event_date, format: :long) %></time>
</article>
<% end %><% cache [event, "v2"] do %>
...
<% end %>
<% cache [event, current_user] do %>
...
<% end %><% cache [event, "v2"] do %>
...
<% end %>
<% cache [event, current_user] do %>
...
<% end %>touch: trueundefinedtouch: trueundefined
```erb
<% cache @event do %>
<h1><%= @event.name %></h1>
<% @event.comments.each do |comment| %>
<% cache comment do %>
<%= render comment %>
<% end %>
<% end %>
<% end %>touch: trueupdated_at
```erb
<% cache @event do %>
<h1><%= @event.name %></h1>
<% @event.comments.each do |comment| %>
<% cache comment do %>
<%= render comment %>
<% end %>
<% end %>
<% end %>touch: trueupdated_at<%# Caches each item individually, multi-read from cache store %>
<%= render partial: "events/event", collection: @events, cached: true %><%# 单独缓存每个条目,从缓存存储中批量读取 %>
<%= render partial: "events/event", collection: @events, cached: true %>Rails.cache.fetch("stats/#{Date.current}", expires_in: 1.hour) do
{ total_events: Event.count, total_revenue: Order.sum(:total_cents) }
endRails.cache.fetch("stats/#{Date.current}", expires_in: 1.hour) do
{ total_events: Event.count, total_revenue: Order.sum(:total_cents) }
endclass Board < ApplicationRecord
def statistics
Rails.cache.fetch([self, "statistics"], expires_in: 1.hour) do
{
total_cards: cards.count,
completed_cards: cards.joins(:closure).count,
total_comments: cards.joins(:comments).count
}
end
end
endclass Board < ApplicationRecord
def statistics
Rails.cache.fetch([self, "statistics"], expires_in: 1.hour) do
{
total_cards: cards.count,
completed_cards: cards.joins(:closure).count,
total_comments: cards.joins(:comments).count
}
end
end
endRails.cache.fetch([self, "stats"], expires_in: 1.hour, race_condition_ttl: 10.seconds) do
expensive_operation
endRails.cache.fetch([self, "stats"], expires_in: 1.hour, race_condition_ttl: 10.seconds) do
expensive_operation
endupdated_atupdated_atclass Card < ApplicationRecord
belongs_to :board, touch: true # Updates board.updated_at
end
class Comment < ApplicationRecord
belongs_to :card, touch: true # Updates card.updated_at -> board.updated_at
endclass Card < ApplicationRecord
belongs_to :board, touch: true # 更新board.updated_at
end
class Comment < ApplicationRecord
belongs_to :card, touch: true # 更新card.updated_at -> board.updated_at
endclass Event < ApplicationRecord
after_commit :invalidate_caches
private
def invalidate_caches
Rails.cache.delete([self, "statistics"])
Rails.cache.delete("featured_events")
end
endclass Event < ApplicationRecord
after_commit :invalidate_caches
private
def invalidate_caches
Rails.cache.delete([self, "statistics"])
Rails.cache.delete("featured_events")
end
endclass CacheSweeper
def self.clear_board_caches(board)
Rails.cache.delete([board, "statistics"])
Rails.cache.delete([board, "card_distribution"])
end
endclass CacheSweeper
def self.clear_board_caches(board)
Rails.cache.delete([board, "statistics"])
Rails.cache.delete([board, "card_distribution"])
end
endundefinedundefinedundefinedundefinedclass CacheWarmerJob < ApplicationJob
queue_as :low
def perform(account)
account.boards.find_each do |board|
board.statistics
board.card_distribution
end
end
endclass CacheWarmerJob < ApplicationJob
queue_as :low
def perform(account)
account.boards.find_each do |board|
board.statistics
board.card_distribution
end
end
endundefinedundefinedundefinedundefinedundefinedundefinedassert_changes -> { board.reload.updated_at } do
card.touch
endundefinedassert_changes -> { board.reload.updated_at } do
card.touch
endundefinedundefinedundefinedget board_url(@board), headers: { "If-None-Match" => etag }
assert_response :not_modified@board.touch
get board_url(@board), headers: { "If-None-Match" => etag }
assert_response :successundefinedget board_url(@board), headers: { "If-None-Match" => etag }
assert_response :not_modified@board.touch
get board_url(@board), headers: { "If-None-Match" => etag }
assert_response :successundefinedundefinedundefinedboard.statistics # Warm cache
card.update!(title: "New title")
assert_nil Rails.cache.read([board, "statistics"])undefinedboard.statistics # 预热缓存
card.update!(title: "New title")
assert_nil Rails.cache.read([board, "statistics"])undefinedclass EventPresenter < BasePresenter
def vendor_count
@vendor_count ||= event.vendors.count
end
endclass EventPresenter < BasePresenter
def vendor_count
@vendor_count ||= event.vendors.count
end
endfresh_whentouch: truecached: truefresh_whentouch: truecached: true