diff options
Diffstat (limited to 'actionpack/lib/action_view/helpers/cache_helper.rb')
-rw-r--r-- | actionpack/lib/action_view/helpers/cache_helper.rb | 181 |
1 files changed, 0 insertions, 181 deletions
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb deleted file mode 100644 index 8693f4f0e4..0000000000 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ /dev/null @@ -1,181 +0,0 @@ -module ActionView - # = Action View Cache Helper - module Helpers - module CacheHelper - # This helper exposes a method for caching fragments of a view - # rather than an entire action or page. This technique is useful - # caching pieces like menus, lists of newstopics, static HTML - # fragments, and so on. This method takes a block that contains - # the content you wish to cache. - # - # The best way to use this is by doing key-based cache expiration - # on top of a cache store like Memcached that'll automatically - # kick out old entries. For more on key-based expiration, see: - # http://37signals.com/svn/posts/3113-how-key-based-cache-expiration-works - # - # When using this method, you list the cache dependency as the name of the cache, like so: - # - # <% cache project do %> - # <b>All the topics on this project</b> - # <%= render project.topics %> - # <% end %> - # - # This approach will assume that when a new topic is added, you'll touch - # the project. The cache key generated from this call will be something like: - # - # views/projects/123-20120806214154/7a1156131a6928cb0026877f8b749ac9 - # ^class ^id ^updated_at ^template tree digest - # - # The cache is thus automatically bumped whenever the project updated_at is touched. - # - # If your template cache depends on multiple sources (try to avoid this to keep things simple), - # you can name all these dependencies as part of an array: - # - # <% cache [ project, current_user ] do %> - # <b>All the topics on this project</b> - # <%= render project.topics %> - # <% end %> - # - # This will include both records as part of the cache key and updating either of them will - # expire the cache. - # - # ==== Template digest - # - # The template digest that's added to the cache key is computed by taking an md5 of the - # contents of the entire template file. This ensures that your caches will automatically - # expire when you change the template file. - # - # Note that the md5 is taken of the entire template file, not just what's within the - # cache do/end call. So it's possible that changing something outside of that call will - # still expire the cache. - # - # Additionally, the digestor will automatically look through your template file for - # explicit and implicit dependencies, and include those as part of the digest. - # - # The digestor can be bypassed by passing skip_digest: true as an option to the cache call: - # - # <% cache project, skip_digest: true do %> - # <b>All the topics on this project</b> - # <%= render project.topics %> - # <% end %> - # - # ==== Implicit dependencies - # - # Most template dependencies can be derived from calls to render in the template itself. - # Here are some examples of render calls that Cache Digests knows how to decode: - # - # render partial: "comments/comment", collection: commentable.comments - # render "comments/comments" - # render 'comments/comments' - # render('comments/comments') - # - # render "header" => render("comments/header") - # - # render(@topic) => render("topics/topic") - # render(topics) => render("topics/topic") - # render(message.topics) => render("topics/topic") - # - # It's not possible to derive all render calls like that, though. Here are a few examples of things that can't be derived: - # - # render group_of_attachments - # render @project.documents.where(published: true).order('created_at') - # - # You will have to rewrite those to the explicit form: - # - # render partial: 'attachments/attachment', collection: group_of_attachments - # render partial: 'documents/document', collection: @project.documents.where(published: true).order('created_at') - # - # === Explicit dependencies - # - # Some times you'll have template dependencies that can't be derived at all. This is typically - # the case when you have template rendering that happens in helpers. Here's an example: - # - # <%= render_sortable_todolists @project.todolists %> - # - # You'll need to use a special comment format to call those out: - # - # <%# Template Dependency: todolists/todolist %> - # <%= render_sortable_todolists @project.todolists %> - # - # The pattern used to match these is /# Template Dependency: ([^ ]+)/, so it's important that you type it out just so. - # You can only declare one template dependency per line. - # - # === External dependencies - # - # If you use a helper method, for example, inside of a cached block and you then update that helper, - # you'll have to bump the cache as well. It doesn't really matter how you do it, but the md5 of the template file - # must change. One recommendation is to simply be explicit in a comment, like: - # - # <%# Helper Dependency Updated: May 6, 2012 at 6pm %> - # <%= some_helper_method(person) %> - # - # Now all you'll have to do is change that timestamp when the helper method changes. - # - # ==== Conditional caching - # - # You can pass :if and :unless options, to conditionally perform or skip the cache. - # - # <%= cache @model, if: some_condition(@model) do %> - # - def cache(name = {}, options = nil, &block) - if controller.perform_caching && conditions_match?(options) - safe_concat(fragment_for(cache_fragment_name(name, options), options, &block)) - else - yield - end - - nil - end - - # This helper returns the name of a cache key for a given fragment cache - # call. By supplying skip_digest: true to cache, the digestion of cache - # fragments can be manually bypassed. This is useful when cache fragments - # cannot be manually expired unless you know the exact key which is the - # case when using memcached. - def cache_fragment_name(name = {}, options = nil) - skip_digest = options && options[:skip_digest] - - if skip_digest - name - else - fragment_name_with_digest(name) - end - end - - private - - def conditions_match?(options) - !(options && (!options.fetch(:if, true) || options.fetch(:unless, false))) - end - - def fragment_name_with_digest(name) #:nodoc: - if @virtual_path - [ - *Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name), - Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context) - ] - else - name - end - end - - # TODO: Create an object that has caching read/write on it - def fragment_for(name = {}, options = nil, &block) #:nodoc: - if fragment = controller.read_fragment(name, options) - fragment - else - # VIEW TODO: Make #capture usable outside of ERB - # This dance is needed because Builder can't use capture - pos = output_buffer.length - yield - output_safe = output_buffer.html_safe? - fragment = output_buffer.slice!(pos..-1) - if output_safe - self.output_buffer = output_buffer.class.new(output_buffer) - end - controller.write_fragment(name, fragment, options) - end - end - end - end -end |