<commit_before>require 'jbuilder'
require 'action_dispatch/http/mime_type'
require 'active_support/cache'

class JbuilderTemplate < Jbuilder
  class << self
    attr_accessor :template_lookup_options
  end

  self.template_lookup_options = { handlers: [:jbuilder] }

  def initialize(context, *args, &block)
    @context = context
    super(*args, &block)
  end

  def partial!(name_or_options, locals = {})
    case name_or_options
    when ::Hash
      # partial! partial: 'name', locals: { foo: 'bar' }
      options = name_or_options
    else
      # partial! 'name', foo: 'bar'
      options = { partial: name_or_options, locals: locals }
      as = locals.delete(:as)
      options[:as] = as if as.present?
      options[:collection] = locals[:collection] if locals.key?(:collection)
    end

    options[:collection] ||= [] if options.key?(:collection)

    _handle_partial_options options
  end

  def array!(collection = [], *attributes, &block)
    options = attributes.extract_options!

    if options.key?(:partial)
      partial! options[:partial], options.merge(collection: collection)
    else
      super
    end
  end

  # 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
  def cache!(key=nil, options={}, &block)
    if @context.controller.perform_caching
      value = ::Rails.cache.fetch(_cache_key(key), options) do
        _scope { yield self }
      end

      _merge(value)
    else
      yield
    end
  end

  protected
    def _handle_partial_options(options)
      options.reverse_merge! locals: {}
      options.reverse_merge! ::JbuilderTemplate.template_lookup_options
      collection = options.delete(:collection)
      as = options[:as]

      if collection && as
        array!(collection) do |member|
          options[:locals].merge! as => member
          options[:locals].merge! collection: collection
          _render_partial options
        end
      else
        _render_partial options
      end
    end

    def _render_partial(options)
      options[:locals].merge! json: self
      @context.render options
    end

    def _cache_key(key)
      if @context.respond_to?(:cache_fragment_name)
        # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
        # should be used instead.
        @context.cache_fragment_name(key)
      elsif @context.respond_to?(:fragment_name_with_digest)
        # Backwards compatibility for period of time when fragment_name_with_digest was made public.
        @context.fragment_name_with_digest(key)
      else
        ::ActiveSupport::Cache.expand_cache_key(key.is_a?(::Hash) ? url_for(key).split('://').last : key, :jbuilder)
      end
    end
<commit_msg>Cleaned up collection handling a little<commit_after>require 'jbuilder'
require 'action_dispatch/http/mime_type'
require 'active_support/cache'

class JbuilderTemplate < Jbuilder
  class << self
    attr_accessor :template_lookup_options
  end

  self.template_lookup_options = { handlers: [:jbuilder] }

  def initialize(context, *args, &block)
    @context = context
    super(*args, &block)
  end

  def partial!(name_or_options, locals = {})
    case name_or_options
    when ::Hash
      # partial! partial: 'name', locals: { foo: 'bar' }
      options = name_or_options
    else
      # partial! 'name', foo: 'bar'
      options = { partial: name_or_options, locals: locals }
      as = locals.delete(:as)
      options[:as] = as if as.present?
      options[:collection] = locals[:collection] if locals.key?(:collection)
    end

    _handle_partial_options options
  end

  def array!(collection = [], *attributes, &block)
    options = attributes.extract_options!

    if options.key?(:partial)
      partial! options[:partial], options.merge(collection: collection)
    else
      super
    end
  end

  # 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
  def cache!(key=nil, options={}, &block)
    if @context.controller.perform_caching
      value = ::Rails.cache.fetch(_cache_key(key), options) do
        _scope { yield self }
      end

      _merge(value)
    else
      yield
    end
  end

  protected
    def _handle_partial_options(options)
      options.reverse_merge! locals: {}
      options.reverse_merge! ::JbuilderTemplate.template_lookup_options
      as = options[:as]

      if as && options.key?(:collection)
        collection = options.delete(:collection) || []
        array!(collection) do |member|
          options[:locals].merge! as => member
          options[:locals].merge! collection: collection
          _render_partial options
        end
      else
        _render_partial options
      end
    end

    def _render_partial(options)
      options[:locals].merge! json: self
      @context.render options
    end

    def _cache_key(key)
      if @context.respond_to?(:cache_fragment_name)
        # Current compatibility, fragment_name_with_digest is private again and cache_fragment_name
        # should be used instead.
        @context.cache_fragment_name(key)
      elsif @context.respond_to?(:fragment_name_with_digest)
        # Backwards compatibility for period of time when fragment_name_with_digest was made public.
        @context.fragment_name_with_digest(key)
      else
        ::ActiveSupport::Cache.expand_cache_key(key.is_a?(::Hash) ? url_for(key).split('://').last : key, :jbuilder)
      end
    end

{'fraction_non_alphanumeric': 0.10361814166808221, 'fraction_numerical': 0.0010191948360794973, 'mean_word_length': 3.0832177531206657, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1987649', 'n_tokens_mistral': 1757, 'n_tokens_neox': 1717, 'n_words': 442}