diff --git a/lib/jbuilder/jbuilder_template.rb b/lib/jbuilder/jbuilder_template.rb index 882c030..feaee62 100644 --- a/lib/jbuilder/jbuilder_template.rb +++ b/lib/jbuilder/jbuilder_template.rb @@ -42,6 +42,27 @@ def cache!(key=nil, options={}) end end + # Caches the json structure at the root using a string rather than the hash structure. This is considerably + # faster, but the drawback is that it only works, as the name hints, at the root. So you cannot + # use this approach to cache deeper inside the hierarchy, like in partials or such. Continue to use #cache! there. + # + # Example: + # + # json.cache_root! @person do + # json.extract! @person, :name, :age + # end + # + # # json.extra 'This will not work either, the root must be exclusive' + def cache_root!(key=nil, options={}) + if @context.controller.perform_caching + raise "cache_root! can't be used after JSON structures have been defined" if @attributes.present? + + @cached_root = _cache_fragment_for([ :root, key ], options) { yield; target! } + else + yield + end + end + # Conditionally caches the json depending in the condition given as first parameter. Has the same # signature as the `cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in # the same way. @@ -55,6 +76,10 @@ def cache_if!(condition, *args) condition ? cache!(*args, &::Proc.new) : yield end + def target! + @cached_root || super + end + def array!(collection = [], *args) options = args.first diff --git a/test/jbuilder_template_test.rb b/test/jbuilder_template_test.rb index e302881..b62277d 100644 --- a/test/jbuilder_template_test.rb +++ b/test/jbuilder_template_test.rb @@ -386,6 +386,35 @@ def assert_collection_rendered(result, context = nil) JBUILDER end + test "caching root structure" do + undef_context_methods :fragment_name_with_digest, :cache_fragment_name + + cache_miss_result = jbuild <<-JBUILDER + json.cache_root! "cachekey" do + json.name "Miss" + end + JBUILDER + + cache_hit_result = jbuild <<-JBUILDER + json.cache_root! "cachekey" do + json.name "Hit" + end + JBUILDER + + assert_equal cache_miss_result, cache_hit_result + end + + test "failing to cache root after attributes have been defined" do + assert_raises ActionView::Template::Error, "cache_root! can't be used after JSON structures have been defined" do + jbuild <<-JBUILDER + json.name "Kaboom" + json.cache_root! "cachekey" do + json.name "Miss" + end + JBUILDER + end + end + test "does not perform caching when controller.perform_caching is false" do controller.perform_caching = false