class JbuilderTemplate

Attributes

template_lookup_options[RW]

Public Class Methods

new(context, *args) click to toggle source
Calls superclass method Jbuilder::new
# File lib/jbuilder/jbuilder_template.rb, line 13
def initialize(context, *args)
  @context = context
  @cached_root = nil
  super(*args)
end

Public Instance Methods

array!(collection = [], *args) click to toggle source
Calls superclass method Jbuilder#array!
# File lib/jbuilder/jbuilder_template.rb, line 117
def array!(collection = [], *args)
  options = args.first

  if args.one? && _partial_options?(options)
    partial! options.merge(collection: collection)
  else
    super
  end
end
cache!(key=nil, options={}) { |self| ... } click to toggle source

Caches the json constructed within the block passed. Has the same signature as the ‘cache` helper method in `ActionView::Helpers::CacheHelper` and so can be used in the same way.

Example:

json.cache! ['v1', @person], expires_in: 10.minutes do
  json.extract! @person, :name, :age
end
# File lib/jbuilder/jbuilder_template.rb, line 67
def cache!(key=nil, options={})
  if @context.controller.perform_caching
    value = _cache_fragment_for(key, options) do
      _scope { yield self }
    end

    merge! value
  else
    yield
  end
end
cache_if!(condition, *args) { || ... } click to toggle source

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.

Example:

json.cache_if! !admin?, @person, expires_in: 10.minutes do
  json.extract! @person, :name, :age
end
# File lib/jbuilder/jbuilder_template.rb, line 109
def cache_if!(condition, *args, &block)
  condition ? cache!(*args, &block) : yield
end
cache_root!(key=nil, options={}) { || ... } click to toggle source

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'
# File lib/jbuilder/jbuilder_template.rb, line 90
def cache_root!(key=nil, options={})
  if @context.controller.perform_caching
    ::Kernel.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
partial!(*args) click to toggle source

Generates JSON using the template specified with the ‘:partial` option. For example, the code below will render the file `views/comments/_comments.json.jbuilder`, and set a local variable comments with all this message’s comments, which can be used inside the partial.

Example:

json.partial! 'comments/comments', comments: @message.comments

There are multiple ways to generate a collection of elements as JSON, as ilustrated below:

Example:

json.array! @posts, partial: 'posts/post', as: :post

# or:
json.partial! 'posts/post', collection: @posts, as: :post

# or:
json.partial! partial: 'posts/post', collection: @posts, as: :post

# or:
json.comments @post.comments, partial: 'comments/comment', as: :comment

Aside from that, the ‘:cached` options is available on Rails >= 6.0. This will cache the rendered results effectively using the multi fetch feature.

Example:

json.array! @posts, partial: "posts/post", as: :post, cached: true

json.comments @post.comments, partial: "comments/comment", as: :comment, cached: true
# File lib/jbuilder/jbuilder_template.rb, line 51
def partial!(*args)
  if args.one? && _is_active_model?(args.first)
    _render_active_model_partial args.first
  else
    _render_explicit_partial(*args)
  end
end
set!(name, object = BLANK, *args) click to toggle source
Calls superclass method Jbuilder#set!
# File lib/jbuilder/jbuilder_template.rb, line 127
def set!(name, object = BLANK, *args)
  options = args.first

  if args.one? && _partial_options?(options)
    _set_inline_partial name, object, options
  else
    super
  end
end
target!() click to toggle source
Calls superclass method Jbuilder#target!
# File lib/jbuilder/jbuilder_template.rb, line 113
def target!
  @cached_root || super
end

Private Instance Methods

_cache_fragment_for(key, options, &block) click to toggle source
# File lib/jbuilder/jbuilder_template.rb, line 184
def _cache_fragment_for(key, options, &block)
  key = _cache_key(key, options)
  _read_fragment_cache(key, options) || _write_fragment_cache(key, options, &block)
end
_read_fragment_cache(key, options = nil) click to toggle source
# File lib/jbuilder/jbuilder_template.rb, line 189
def _read_fragment_cache(key, options = nil)
  @context.controller.instrument_fragment_cache :read_fragment, key do
    ::Rails.cache.read(key, options)
  end
end
_render_partial(options) click to toggle source
# File lib/jbuilder/jbuilder_template.rb, line 179
def _render_partial(options)
  options[:locals].merge! json: self
  @context.render options
end
_render_partial_with_options(options) click to toggle source
# File lib/jbuilder/jbuilder_template.rb, line 139
def _render_partial_with_options(options)
  options.reverse_merge! locals: options.except(:partial, :as, :collection, :cached)
  options.reverse_merge! ::JbuilderTemplate.template_lookup_options
  as = options[:as]

  if as && options.key?(:collection) && CollectionRenderer.supported?
    collection = options.delete(:collection) || []
    partial = options.delete(:partial)
    options[:locals].merge!(json: self)
    collection = EnumerableCompat.new(collection) if collection.respond_to?(:count) && !collection.respond_to?(:size)

    if options.has_key?(:layout)
      ::Kernel.raise ::NotImplementedError, "The `:layout' option is not supported in collection rendering."
    end

    if options.has_key?(:spacer_template)
      ::Kernel.raise ::NotImplementedError, "The `:spacer_template' option is not supported in collection rendering."
    end

    results = CollectionRenderer
      .new(@context.lookup_context, options) { |&block| _scope(&block) }
      .render_collection_with_partial(collection, partial, @context, nil)

    array! if results.respond_to?(:body) && results.body.nil?
  elsif as && options.key?(:collection) && !CollectionRenderer.supported?
    # For Rails <= 5.2:
    as = as.to_sym
    collection = options.delete(:collection)
    locals = options.delete(:locals)
    array! collection do |member|
      member_locals = locals.clone
      member_locals.merge! collection: collection
      member_locals.merge! as => member
      _render_partial options.merge(locals: member_locals)
    end
  else
    _render_partial options
  end
end
_write_fragment_cache(key, options = nil) { || ... } click to toggle source
# File lib/jbuilder/jbuilder_template.rb, line 195
def _write_fragment_cache(key, options = nil)
  @context.controller.instrument_fragment_cache :write_fragment, key do
    yield.tap do |value|
      ::Rails.cache.write(key, value, options)
    end
  end