Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional Page Caching [Solution: Conditional Fragment Caching]

Suppose that I have controller home_controller.rb with action index.

I want to cache index page so I'm doing:

caches_page :index

but want it to cache only for users that are not signed in. If I'll make conditional like:

caches_page :index, :if => :user_not_signed_in?

Page will be cached while first not logged in user comes. Now every logged in user also see not-logged in content. Is there a way to separate this action without changing url?

like image 538
dfens Avatar asked May 30 '11 08:05

dfens


People also ask

What is fragment caching in Rails?

Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in. For example, if you wanted to cache each product on a page, you could use this code: <% @products.

What are sweepers in Rails?

1.4 Sweepers This class is an Observer that looks for changes to an object via callbacks, and when a change occurs it expires the caches associated with that object in an around or after filter.

How do I use Redis cache Rails?

To use Redis as a Rails cache store, use a dedicated cache instance that's set up as an LRU (Last Recently Used) cache instead of pointing the store at your existing Redis server, to make sure entries are dropped from the store when it reaches its maximum size.

Is Rails cache thread safe?

Keep it in memory thread_mattr_accessor method which makes it easy to build a trivial thread-safe cache service. Rails' implementation ensures every thread has its own storage location for cached_value ; therefore this should be thread-safe (assuming #compute_value can safely run both concurrently and in parallel).


2 Answers

What you want couldn't be achieved;

A page is cached or is not cached. The process checks the existence of a html file or process it.

Still you have two alternatives:

  • use action caching or fragment caching (not recommended)

  • more recommended: load user specific part with ajax so you'll only have one page always cached and specific data inserted dynamically (like stackoverflow)

Here are state of the art explanations: http://railslab.newrelic.com/scaling-rails

like image 156
apneadiving Avatar answered Sep 21 '22 20:09

apneadiving


The accepted answer is now out of date, as conditional caching is now available in Rails 4. A pull request was merged into 4.0.0rc1 that allows for :if and :unless parameters to be passed to cache. This allows templates to be DRY, since there is no longer a need to duplicate the conditionally cached block.

Usage:

<% cache [ @user, 'form' ], :unless => @user.changed? do %>
  <%= render partial: 'shared/error_messages', locals: {instance: @user} %>
  <%= form_for @user do |f| %>
    <div class="field">
      <div><%= f.label :name %></div>
      <div><%= f.text_field :name %></div>
    </div>
    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>
<% end %>
like image 43
platforms Avatar answered Sep 19 '22 20:09

platforms