Action View 緩存輔助程式
執行個體公開方法
cache(name = {}, options = {}, &block) 連結
此輔助程式公開一個方法,用於將檢視區段快取,而不是整個動作或頁面。此技術可用於快取類似選單、新主題清單、靜態 HTML 區段等區段。此方法採用一個區段,該區段包含您希望快取的內容。
使用的最理想方式為在 Memcached 或 Redis 等快取儲存的上方執行可回收金鑰快取到期,它會自動將舊的項目踢出。
在使用此方法時,您會將快取相關性列為快取的名稱,如下所示
<% cache project do %>
<b>All the topics on this project</b>
<%= render project.topics %>
<% end %>
這種方法會假設當新增新主題時,您會變更專案。從此呼叫產生的快取金鑰將類似於
views/template/action:7a1156131a6928cb0026877f8b749ac9/projects/123
^template path ^template tree digest ^class ^id
此快取金鑰是穩定的,但它已與一個從專案記錄衍生的快取版本結合在一起。當專案更新 updated_at 時,cache_version 會變更,即使金鑰保持穩定。這表示,與傳統的金鑰快取到期方法不同的是,您不會產生快取垃圾、未使用的金鑰,這只是因為相關記錄已更新。
如果您的範本快取依賴於多個來源(請避免這樣做,以維持簡單性),您可以將所有這些相關性命名為陣列的一部分
<% cache [ project, current_user ] do %>
<b>All the topics on this project</b>
<%= render project.topics %>
<% end %>
這會將兩筆紀錄都包含為快取金鑰的一部分,而兩個金鑰任何一個更新都會使快取到期。
範本摘要
加入快取金鑰的範本摘要是透過建立整個範本檔案內容的 MD5 進行運算。這可確保在變更範本檔案時,您的快取會自動到期。
請注意,建立 MD5 是採用整個範本檔案,而不只是在快取 do/end 呼叫內的內容。因此,變更該呼叫以外的內容仍可能會使快取到期。
此外,摘要器會自動透過您的範本檔案尋找明確和隱含的相關性,並將它們包含為摘要的一部分。
摘要器可透過將 skip_digest: true 作為選項傳遞至快取呼叫,然後略過
<% cache project, skip_digest: true do %>
<b>All the topics on this project</b>
<%= render project.topics %>
<% end %>
隱含相關性
大多數的範本相關性都可以從範本本身在 render 中的呼叫中衍生。以下是快取摘要知道如何解碼的一些 render 呼叫範例
render partial: "comments/comment", collection: commentable.comments
render "comments/comments"
render 'comments/comments'
render('comments/comments')
render "header" # translates to render("comments/header")
render(@topic) # translates to render("topics/topic")
render(topics) # translates to render("topics/topic")
render(message.topics) # translates to render("topics/topic")
雖然如此,無法衍生所有類似的 render 呼叫。以下是無法衍生的幾個範例
render group_of_attachments
render @project.documents.where(published: true).order('created_at')
您必須將這些改寫為明確形式
render partial: 'attachments/attachment', collection: group_of_attachments
render partial: 'documents/document', collection: @project.documents.where(published: true).order('created_at')
最後一種類型相關性可以隱含地決定
render "maintenance_tasks/runs/info/#{run.status}"
由於傳遞給 render 的值會結束內插,Action View 會將 “maintenance_tasks/runs/info” 資料夾中的所有部分標記為相關性。
明確相關性
有時您會遇到根本無法衍生的範本相關性。當您在輔助程式中有範本呈現時,通常會發生這種情況。以下是範例
<%= render_sortable_todolists @project.todolists %>
您需要使用特殊註解格式來呼叫它們
<%# Template Dependency: todolists/todolist %>
<%= render_sortable_todolists @project.todolists %>
在某些情況下,例如單一資料表繼承設定中,可能會有一堆明確的相依性。您可以使用萬用字元來比對目錄中的任何範本,無需寫出每個範本
<%# Template Dependency: events/* %>
<%= render_categorizable_events @person.events %>
這會將目錄中的每個範本標記為相依項。若要找到這些範本,必須從 app/views
絕對定義萬用字元路徑,或以 prepend_view_path
或 append_view_path
新增其他路徑。這樣一來,app/views/recordings/events
的萬用字元就會變成 recordings/events/*
等。
用於比對明確相依項的模式為 /# Template Dependency: (\S+)/
,因此務必完全照樣輸入。每行只能宣告一個範本相依性。
外部相依性
例如,如果您在快取區塊內使用輔助方法,然後更新該輔助方法,您也必須增加快取。執行方式並不要緊,但範本檔案的 MD5 一定要變更。一個建議是直接用註解說明,例如
<%# Helper Dependency Updated: May 6, 2012 at 6pm %>
<%= some_helper_method(person) %>
現在您只需在輔助方法變更時,變更該時間戳記即可。
集合快取
繪製每個物件使用相同偏好的物件集合時,可以傳遞一個 :cached
選項。
針對這樣繪製的集合
<%= render partial: 'projects/project', collection: @projects, cached: true %>
cached: true
會讓 Action View 的繪製一次從快取讀取多個範本,而非每個範本呼叫一次。
集合中尚未快取的範本會寫入快取。
和個別的範本片段快取十分搭配。例如,如果集合繪製的範本像這樣快取
# projects/_project.html.erb
<% cache project do %>
<%# ... %>
<% end %>
任何集合繪製都會在嘗試一次讀取多個範本時,找到那些快取的範本。
如果您的集合快取取決於多個來源(為了簡化起見,請避免這樣做),您可以將所有這些相依性命名為回傳陣列的區塊的一部分
<%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %>
這會將兩筆紀錄都包含為快取金鑰的一部分,而兩個金鑰任何一個更新都會使快取到期。
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 176 def cache(name = {}, options = {}, &block) if controller.respond_to?(:perform_caching) && controller.perform_caching CachingRegistry.track_caching do name_options = options.slice(:skip_digest) safe_concat(fragment_for(cache_fragment_name(name, **name_options), options, &block)) end else yield end nil end
cache_fragment_name(name = {}, skip_digest: nil, digest_path: nil) 連結
這個輔助方法會回傳特定片段快取呼叫的快取金鑰名稱。透過在快取中提供 skip_digest: true
,可以手動略過快取片段的消化作用。當快取片段無法手動過期,除非您知道確切金鑰(在使用快取記憶體的情況下),這項功能會很有用。
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 248 def cache_fragment_name(name = {}, skip_digest: nil, digest_path: nil) if skip_digest name else fragment_name_with_digest(name, digest_path) end end
cache_if(condition, name = {}, options = {}, &block) 連結
如果 condition
為真,快取檢視的片段
<% cache_if admin?, project do %>
<b>All the topics on this project</b>
<%= render project.topics %>
<% end %>
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 223 def cache_if(condition, name = {}, options = {}, &block) if condition cache(name, options, &block) else yield end nil end
cache_unless(condition, name = {}, options = {}, &block) 連結
除非 condition
為真,否則快取檢視的片段
<% cache_unless admin?, project do %>
<b>All the topics on this project</b>
<%= render project.topics %>
<% end %>
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 239 def cache_unless(condition, name = {}, options = {}, &block) cache_if !condition, name, options, &block end
caching?() 連結
回傳目前檢視片段是否在 cache
區塊中。
當某些片段無法快取時很有用
<% cache project do %>
<% raise StandardError, "Caching private data!" if caching? %>
<% end %>
來源:顯示 | 在 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 196 def caching? CachingRegistry.caching? end
無法快取!() 連結
從 快取
區塊內呼叫時,會引發 UncacheableFragmentError
。
用於表示無法參與區塊快取的輔助函式方法
def project_name_with_time(project)
uncacheable!
"#{project.name} - #{Time.now}"
end
# Which will then raise if used within a +cache+ block:
<% cache project do %>
<%= project_name_with_time(project) %>
<% end %>
來源:顯示 | 於 GitHub 上
# File actionview/lib/action_view/helpers/cache_helper.rb, line 213 def uncacheable! raise UncacheableFragmentError, "can't be fragment cached" if caching? end