1 应用如果这部分代码是topics/list的一部分,
调用的时候
Fragment是用来cache一个block的时候使用的,
常用于一个页面的页面一部分变化,一部分不变化的情况,
- <b>Hello <%= @name %></b>
- <% cache do %>
- All the topics in the system:
- <%= render :partial => "topic", :collection => Topic.find(:all) %>
- <% end %>
使用
expire_fragment(:controller => "topics", :action => "list")
使之失效
我们也可以使用下面这句来指定多个fragment:
<% cache(:action => "list", :action_suffix => "all_topics") do %>
使用
expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")
使之失效
2 源代码分析
- def self.included(base) #:nodoc:
- base.class_eval do
- # 类方法
- class << self
- def fragment_cache_store=(store_option) #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store= method is now use cache_store=')
- self.cache_store = store_option
- end
- def fragment_cache_store #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store method is now use cache_store')
- cache_store
- end
- end
- # 实例方法
- def fragment_cache_store=(store_option) #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store= method is now use cache_store=')
- self.cache_store = store_option
- end
- def fragment_cache_store #:nodoc:
- ActiveSupport::Deprecation.warn('The fragment_cache_store method is now use cache_store')
- cache_store
- end
- end
- end
- def fragment_cache_key(key) # 声称key字符串
- ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
- end
- def fragment_for(block, name = {}, options = nil) #:nodoc:
- unless perform_caching then block.call; return end
- buffer = yield
- if cache = read_fragment(name, options) #如果读取到了cache内容,那么返回内容
- buffer.concat(cache)
- else # 如果没有读取到
- pos = buffer.length
- block.call
- write_fragment(name, buffer[pos..-1], options)
- end
- end
- # Writes <tt>content</tt> to the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
- def write_fragment(key, content, options = nil)
- return unless cache_configured?
- key = fragment_cache_key(key)
- self.class.benchmark "Cached fragment miss: #{key}" do
- cache_store.write(key, content, options)
- end
- content
- end
- # Reads a cached fragment from the location signified by <tt>key</tt> (see <tt>expire_fragment</tt> for acceptable formats)
- def read_fragment(key, options = nil)
- return unless cache_configured?
- key = fragment_cache_key(key)
- self.class.benchmark "Cached fragment hit: #{key}" do
- cache_store.read(key, options)
- end
- end
- # Check if a cached fragment from the location signified by <tt>key</tt> exists (see <tt>expire_fragment</tt> for acceptable formats)
- def fragment_exist?(key, options = nil)
- return unless cache_configured?
- key = fragment_cache_key(key)
- self.class.benchmark "Cached fragment exists?: #{key}" do
- cache_store.exist?(key, options)
- end
- end
- # Name can take one of three forms:
- # * String: This would normally take the form of a path like "pages/45/notes"
- # * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }
- # * Regexp: Will destroy all the matched fragments, example:
- # %r{pages//d*/notes}
- # Ensure you do not specify start and finish in the regex (^$) because
- # the actual filename matched looks like ./cache/filename/path.cache
- # Regexp expiration is only supported on caches that can iterate over
- # all keys (unlike memcached).
- def expire_fragment(key, options = nil)
- return unless cache_configured?
- key = key.is_a?(Regexp) ? key : fragment_cache_key(key)
- if key.is_a?(Regexp)
- self.class.benchmark "Expired fragments matching: #{key.source}" do
- cache_store.delete_matched(key, options) #支持正则表达式失效策略
- end
- else
- self.class.benchmark "Expired fragment: #{key}" do
- cache_store.delete(key, options) #支持一般的key失效策略
- end
- end
- end
我们提前看看View里面的:
- def cache(name = {}, options = nil, &block)
- handler = Template.handler_class_for_extension(current_render_extension.to_sym)
- handler.new(@controller).cache_fragment(block, name, options)
- end
- def cache_fragment(block, name = {}, options = nil)
- @view.fragment_for(block, name, options) do
- eval('xml.target!', block.binding)
- end
- end

本文深入探讨了Rails中Fragment缓存的应用场景和技术细节,包括如何使用Fragment缓存提高页面加载效率,以及源代码级别的实现原理分析。
:ActionController::Caching4 FragmentCache&spm=1001.2101.3001.5002&articleId=3436380&d=1&t=3&u=856d739a9da34f6cbc617295fba23b3c)
2034

被折叠的 条评论
为什么被折叠?



