class Jbuilder

def self.deep_format_keys(value = true)

Same as instance method deep_format_keys! except sets the default.
def self.deep_format_keys(value = true)
  @@deep_format_keys = value
end

def self.encode(*args, &block)

Yields a builder and automatically turns the result into a JSON string
def self.encode(*args, &block)
  new(*args, &block).target!
end

def self.ignore_nil(value = true)

Same as instance method ignore_nil! except sets the default.
def self.ignore_nil(value = true)
  @@ignore_nil = value
end

def self.key_format(*args)

Same as the instance method key_format! except sets the default.
def self.key_format(*args)
  @@key_formatter = KeyFormatter.new(*args)
end

def _blank?(value=@attributes)

def _blank?(value=@attributes)
  BLANK == value
end

def _extract_hash_values(object, attributes)

def _extract_hash_values(object, attributes)
  attributes.each{ |key| _set_value key, _format_keys(object.fetch(key)) }
end

def _extract_method_values(object, attributes)

def _extract_method_values(object, attributes)
  attributes.each{ |key| _set_value key, _format_keys(object.public_send(key)) }
end

def _format_keys(hash_or_array)

def _format_keys(hash_or_array)
  return hash_or_array unless @deep_format_keys
  if ::Array === hash_or_array
    hash_or_array.map { |value| _format_keys(value) }
  elsif ::Hash === hash_or_array
    ::Hash[hash_or_array.collect { |k, v| [_key(k), _format_keys(v)] }]
  else
    hash_or_array
  end
end

def _is_collection?(object)

def _is_collection?(object)
  _object_respond_to?(object, :map, :count) && NON_ENUMERABLES.none?{ |klass| klass === object }
end

def _key(key)

def _key(key)
  @key_formatter ? @key_formatter.format(key) : key.to_s
end

def _map_collection(collection)

def _map_collection(collection)
  collection.map do |element|
    _scope{ yield element }
  end - [BLANK]
end

def _merge_block(key)

def _merge_block(key)
  current_value = _blank? ? BLANK : @attributes.fetch(_key(key), BLANK)
  ::Kernel.raise NullError.build(key) if current_value.nil?
  new_value = _scope{ yield self }
  _merge_values(current_value, new_value)
end

def _merge_values(current_value, updates)

def _merge_values(current_value, updates)
  if _blank?(updates)
    current_value
  elsif _blank?(current_value) || updates.nil? || current_value.empty? && ::Array === updates
    updates
  elsif ::Array === current_value && ::Array === updates
    current_value + updates
  elsif ::Hash === current_value && ::Hash === updates
    current_value.deep_merge(updates)
  else
    ::Kernel.raise MergeError.build(current_value, updates)
  end
end

def _object_respond_to?(object, *methods)

def _object_respond_to?(object, *methods)
  methods.all?{ |m| object.respond_to?(m) }
end

def _scope

def _scope
  parent_attributes, parent_formatter, parent_deep_format_keys = @attributes, @key_formatter, @deep_format_keys
  @attributes = BLANK
  yield
  @attributes
ensure
  @attributes, @key_formatter, @deep_format_keys = parent_attributes, parent_formatter, parent_deep_format_keys
end

def _set_value(key, value)

def _set_value(key, value)
  ::Kernel.raise NullError.build(key) if @attributes.nil?
  ::Kernel.raise ArrayError.build(key) if ::Array === @attributes
  return if @ignore_nil && value.nil? or _blank?(value)
  @attributes = {} if _blank?
  @attributes[_key(key)] = value
end

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

[1,2,3]

json.array! [1, 2, 3]

If you omit the block then you can set the top level array directly:

{ "people": [ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ] }

end
json.age calculate_age(person.birthday)
json.name person.name
json.people(@people) do |person|

It's generally only needed to use this method for top-level arrays. If you have named arrays, you can do:

json.(@people) { |person| ... }

You can use the call syntax instead of an explicit extract! call:

[ { "name": David", "age": 32 }, { "name": Jamie", "age": 31 } ]

end
json.age calculate_age(person.birthday)
json.name person.name
json.array!(@people) do |person|

Example:

an element of the resulting array.
Turns the current element into an array and iterates over the passed collection, adding each iteration as
def array!(collection = [], *attributes, &block)
  array = if collection.nil?
    []
  elsif ::Kernel.block_given?
    _map_collection(collection, &block)
  elsif attributes.any?
    _map_collection(collection) { |element| extract! element, *attributes }
  else
    _format_keys(collection.to_a)
  end
  @attributes = _merge_values(@attributes, array)
end

def attributes!

Returns the attributes of the current builder.
def attributes!
  @attributes
end

def call(object, *attributes, &block)

def call(object, *attributes, &block)
  if ::Kernel.block_given?
    array! object, &block
  else
    extract! object, *attributes
  end
end

def child!

end
json.content comment.formatted_content
json.comments(@post.comments) do |comment|

More commonly, you'd use the combined iterator, though:

{ "comments": [ { "content": "hello" }, { "content": "world" } ]}

end
json.child! { json.content "world" }
json.child! { json.content "hello" }
json.comments do

Example:

Turns the current element into an array and yields a builder to add a hash.
def child!
  @attributes = [] unless ::Array === @attributes
  @attributes << _scope{ yield self }
end

def deep_format_keys!(value = true)


{ "settings": { "someValue": "abc" }}

json.settings({some_value: "abc"})
json.deep_format_keys!
json.key_format! camelize: :lower

{ "settings": { "some_value": "abc" }}

json.settings({some_value: "abc"})
json.key_format! camelize: :lower

Example:

methods like set!, merge! or array!.
Deeply apply key format to nested hashes and arrays passed to
def deep_format_keys!(value = true)
  @deep_format_keys = value
end

def extract!(object, *attributes)

json.(@person, :name, :age)

You can also use the call syntax instead of an explicit extract! call:

{ "name": David", "age": 32 }, { "name": Jamie", "age": 31 }

json.extract! @person, :name, :age

@person = { name: 'David', age: 32 }

or you can utilize a Hash

@person = Struct.new(:name, :age).new('David', 32)

Example:

Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
def extract!(object, *attributes)
  if ::Hash === object
    _extract_hash_values(object, attributes)
  else
    _extract_method_values(object, attributes)
  end
end

def ignore_nil!(value = true)


{}

json.id User.new.id
json.ignore_nil!

{ "id": null }

json.id User.new.id
json.ignore_nil! false
Example:

not to receive keys which have null values.
for JSON clients that don't deal well with nil values, and would prefer
If you want to skip adding nil values to your JSON hash. This is useful
def ignore_nil!(value = true)
  @ignore_nil = value
end

def initialize(options = {})

def initialize(options = {})
  @attributes = {}
  @key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
  @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)
  @deep_format_keys = options.fetch(:deep_format_keys, @@deep_format_keys)
  yield self if ::Kernel.block_given?
end

def key_format!(*args)


{ "_first_name": "David" }

json.first_name "David"
json.key_format! ->(key){ "_" + key }

Lambdas can also be used.

{ "firstName": "David" }

json.first_name "David"
json.key_format! camelize: :lower

You can pass parameters to the method using a hash pair.

{ "AUTHOR": { "NAME": "David", "AGE": 32 } }

end
json.age 32
json.name "David"
json.author do
json.key_format! :upcase

Example:

the key. You can also pass in lambdas for more complex transformations.
will cause that function to be called on the key. So :upcase will upper case
Specifies formatting to be applied to the key. Passing in a name of a function
def key_format!(*args)
  @key_formatter = KeyFormatter.new(*args)
end

def merge!(object)

Merges hash, array, or Jbuilder instance into current builder.
def merge!(object)
  hash_or_array = ::Jbuilder === object ? object.attributes! : object
  @attributes = _merge_values(@attributes, _format_keys(hash_or_array))
end

def method_missing(*args, &block)

def method_missing(*args, &block)
  if ::Kernel.block_given?
    set!(*args, &block)
  else
    set!(*args)
  end
end

def nil!

Returns the nil JSON.
def nil!
  @attributes = nil
end

def set!(key, value = BLANK, *args, &block)

def set!(key, value = BLANK, *args, &block)
  result = if ::Kernel.block_given?
    if !_blank?(value)
      # json.comments @post.comments { |comment| ... }
      # { "comments": [ { ... }, { ... } ] }
      _scope{ array! value, &block }
    else
      # json.comments { ... }
      # { "comments": ... }
      _merge_block(key){ yield self }
    end
  elsif args.empty?
    if ::Jbuilder === value
      # json.age 32
      # json.person another_jbuilder
      # { "age": 32, "person": { ...  }
      _format_keys(value.attributes!)
    else
      # json.age 32
      # { "age": 32 }
      _format_keys(value)
    end
  elsif _is_collection?(value)
    # json.comments @post.comments, :content, :created_at
    # { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
    _scope{ array! value, *args }
  else
    # json.author @post.creator, :name, :email_address
    # { "author": { "name": "David", "email_address": "david@loudthinking.com" } }
    _merge_block(key){ extract! value, *args }
  end
  _set_value key, result
end

def target!

Encodes the current builder as JSON.
def target!
  @attributes.to_json
end