My Rails app has Post and Member models. Within posts/:id/show contains a “like” button which Members can click, or “Unlike” if @member has already “liked” this @post already.
(This button will link to a post action that does some ajax and makes the “like” button change into a “unlike” button)
Whats the best practice for caching the button? (below code obviously doesn’t cache the button html).
Should I add :touch => true to member.rb, and then make a cache key for the button e.g. <% cache ['V1', @post, @member, 'like_button'] ? (seems redundant?)
post.rb
has_many :likes
like.rb
belongs_to :member
belongs_to :post
member.rb
has_many :likes
*posts/show.html.erb *
<% cache ['V1', @post, 'show'] do %>
<h1>@post.title</h1>
<div class="content">@post.content</div>
<% end %>
<%= render 'like_button', :post=> @post, :member => @member %>
** posts/_like_button.html.erb **
<% if member.liked_post?(post) %>
<%= link_to unlike_post_path(post), :method => :post, :remote => true, :class => 'btn' %>
<% else %>
<%= link_to like_post_path(post), :method => :post, :remote => true, :class => 'btn' %>
<% end %>
You can do something along these lines:
This gives your 2 different cached versions of the fragment – one each for the ‘liked’ and ‘not liked’ states. This is better than 1 version per user.
YOu run the risk here of someone adding code to the like_button partial that uses more of the @member parameter, and that isn’t part of the cache key, so you’ll get incorrect results.
For this case, I’d change the like_button partial to take the same parameter as the cache call – @member.liked_post(@post) — to make it clear that this is the only value used inside the partial code.
With the new partial: