Skip to content

Commit

Permalink
Cache root (#370)
Browse files Browse the repository at this point in the history
Add cache_root! for faster root caching
  • Loading branch information
dhh authored Nov 28, 2016
1 parent ed5e4c6 commit 9f8694f
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
25 changes: 25 additions & 0 deletions lib/jbuilder/jbuilder_template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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

Expand Down
29 changes: 29 additions & 0 deletions test/jbuilder_template_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 9f8694f

Please sign in to comment.