Skip to content

Instantly share code, notes, and snippets.

@cmer
Created March 27, 2012 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cmer/2221345 to your computer and use it in GitHub Desktop.
Save cmer/2221345 to your computer and use it in GitHub Desktop.
Poor man's caching for Jbuilder
# app/views/users/_user.json.jbuilder
json.(user, :id, :name, :age, :gender)
class ApplicationController < ActionController::Base
protect_from_forgery
def cached_jbuilder(obj, opts = {})
cache_key = (opts[:cache_key_prefix] || []) + Array.wrap(obj)
cached = read_fragment(cache_key)
if cached
out = view_context.raw cached
elsif obj.is_a?(Array)
out = ""
obj.each_index do |i|
is_last = (obj.length - 1 == i)
out += cached_jbuilder(obj[i], opts) + (!is_last ? "," : "")
end
out = "[#{out}]"
write_fragment cache_key, out
out
else
out = view_context.raw render_to_string partial: obj, locals: { obj.class.to_s.tableize.to_sym => obj }
write_fragment cache_key, out
out
end
view_context.raw out
end
end
<% # app/views/users/index.json.erb -%>
{"users":<%= controller.cached_jbuilder @users -%>}
@cmer
Copy link
Author

cmer commented Mar 27, 2012

The idea behind this is to start building the JSON output through an ERB template. We can then easily use the caching helpers to partially or entirely cache the resulting JSON.

In this example, if @users is populated with 3 records when we render index.json.erb, a total of 4 cache keys will be created: 3 JSON string representations of each user, and 1 JSON string containing all 3 users in an array. If one user changes, the array cache is busted, as well as the cache for the record that has changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment