Skip to content

Commit 9f8694f

Browse files
author
David Heinemeier Hansson
authored
Cache root (#370)
Add cache_root! for faster root caching
1 parent ed5e4c6 commit 9f8694f

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

lib/jbuilder/jbuilder_template.rb

+25
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@ def cache!(key=nil, options={})
4242
end
4343
end
4444

45+
# Caches the json structure at the root using a string rather than the hash structure. This is considerably
46+
# faster, but the drawback is that it only works, as the name hints, at the root. So you cannot
47+
# use this approach to cache deeper inside the hierarchy, like in partials or such. Continue to use #cache! there.
48+
#
49+
# Example:
50+
#
51+
# json.cache_root! @person do
52+
# json.extract! @person, :name, :age
53+
# end
54+
#
55+
# # json.extra 'This will not work either, the root must be exclusive'
56+
def cache_root!(key=nil, options={})
57+
if @context.controller.perform_caching
58+
raise "cache_root! can't be used after JSON structures have been defined" if @attributes.present?
59+
60+
@cached_root = _cache_fragment_for([ :root, key ], options) { yield; target! }
61+
else
62+
yield
63+
end
64+
end
65+
4566
# Conditionally caches the json depending in the condition given as first parameter. Has the same
4667
# signature as the `cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in
4768
# the same way.
@@ -55,6 +76,10 @@ def cache_if!(condition, *args)
5576
condition ? cache!(*args, &::Proc.new) : yield
5677
end
5778

79+
def target!
80+
@cached_root || super
81+
end
82+
5883
def array!(collection = [], *args)
5984
options = args.first
6085

test/jbuilder_template_test.rb

+29
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,35 @@ def assert_collection_rendered(result, context = nil)
386386
JBUILDER
387387
end
388388

389+
test "caching root structure" do
390+
undef_context_methods :fragment_name_with_digest, :cache_fragment_name
391+
392+
cache_miss_result = jbuild <<-JBUILDER
393+
json.cache_root! "cachekey" do
394+
json.name "Miss"
395+
end
396+
JBUILDER
397+
398+
cache_hit_result = jbuild <<-JBUILDER
399+
json.cache_root! "cachekey" do
400+
json.name "Hit"
401+
end
402+
JBUILDER
403+
404+
assert_equal cache_miss_result, cache_hit_result
405+
end
406+
407+
test "failing to cache root after attributes have been defined" do
408+
assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do
409+
jbuild <<-JBUILDER
410+
json.name "Kaboom"
411+
json.cache_root! "cachekey" do
412+
json.name "Miss"
413+
end
414+
JBUILDER
415+
end
416+
end
417+
389418
test "does not perform caching when controller.perform_caching is false" do
390419
controller.perform_caching = false
391420

0 commit comments

Comments
 (0)