Class: Jbuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/jbuilder.rb,
lib/jbuilder/blank.rb,
lib/jbuilder/errors.rb,
lib/jbuilder/railtie.rb,
lib/jbuilder/key_formatter.rb,
lib/jbuilder/collection_renderer.rb

Direct Known Subclasses

JbuilderTemplate

Defined Under Namespace

Modules: CollectionRenderable Classes: ArrayError, Blank, CollectionRenderer, DependencyTracker, EnumerableCompat, KeyFormatter, MergeError, NullError, Railtie

Constant Summary collapse

BLANK =
Blank.new
NON_ENUMERABLES =
defined?(::OpenStruct) ? [::Struct, ::OpenStruct].to_set : [::Struct].to_set
@@key_formatter =
nil
@@ignore_nil =
false
@@deep_format_keys =
false

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) {|_self| ... } ⇒ Jbuilder

Returns a new instance of Jbuilder.

Yields:

  • (_self)

Yield Parameters:

  • _self (Jbuilder)

    the object that the method was called on



18
19
20
21
22
23
24
25
26
# File 'lib/jbuilder.rb', line 18

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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, &block) ⇒ Object



71
72
73
74
75
76
77
# File 'lib/jbuilder.rb', line 71

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

Class Method Details

.deep_format_keys(value = true) ⇒ Object

Same as instance method deep_format_keys! except sets the default.



161
162
163
# File 'lib/jbuilder.rb', line 161

def self.deep_format_keys(value = true)
  @@deep_format_keys = value
end

.encode(*args, &block) ⇒ Object

Yields a builder and automatically turns the result into a JSON string



29
30
31
# File 'lib/jbuilder.rb', line 29

def self.encode(*args, &block)
  new(*args, &block).target!
end

.ignore_nil(value = true) ⇒ Object

Same as instance method ignore_nil! except sets the default.



136
137
138
# File 'lib/jbuilder.rb', line 136

def self.ignore_nil(value = true)
  @@ignore_nil = value
end

.key_format(*args) ⇒ Object

Same as the instance method key_format! except sets the default.



112
113
114
# File 'lib/jbuilder.rb', line 112

def self.key_format(*args)
  @@key_formatter = KeyFormatter.new(*args)
end

Instance Method Details

#array!(collection = [], *attributes, &block) ⇒ Object

Turns the current element into an array and iterates over the passed collection, adding each iteration as an element of the resulting array.

Example:

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

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

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

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

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

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

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

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

json.array! [1, 2, 3]

[1,2,3]


216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/jbuilder.rb', line 216

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

#attributes!Object

Returns the attributes of the current builder.



271
272
273
# File 'lib/jbuilder.rb', line 271

def attributes!
  @attributes
end

#call(object, *attributes, &block) ⇒ Object



255
256
257
258
259
260
261
# File 'lib/jbuilder.rb', line 255

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

#child!Object

Turns the current element into an array and yields a builder to add a hash.

Example:

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

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

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

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


181
182
183
184
# File 'lib/jbuilder.rb', line 181

def child!
  @attributes = [] unless ::Array === @attributes
  @attributes << _scope{ yield self }
end

#deep_format_keys!(value = true) ⇒ Object

Deeply apply key format to nested hashes and arrays passed to methods like set!, merge! or array!.

Example:

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

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

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

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


156
157
158
# File 'lib/jbuilder.rb', line 156

def deep_format_keys!(value = true)
  @deep_format_keys = value
end

#extract!(object, *attributes) ⇒ Object

Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.

Example:

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

or you can utilize a Hash

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

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

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

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

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


247
248
249
250
251
252
253
# File 'lib/jbuilder.rb', line 247

def extract!(object, *attributes)
  if ::Hash === object
    _extract_hash_values(object, attributes)
  else
    _extract_method_values(object, attributes)
  end
end

#ignore_nil!(value = true) ⇒ Object

If you want to skip adding nil values to your JSON hash. This is useful for JSON clients that don’t deal well with nil values, and would prefer not to receive keys which have null values.

Example:

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

{ "id": null }

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

{}


131
132
133
# File 'lib/jbuilder.rb', line 131

def ignore_nil!(value = true)
  @ignore_nil = value
end

#key_format!(*args) ⇒ Object

Specifies formatting to be applied to the key. Passing in a name of a function will cause that function to be called on the key. So :upcase will upper case the key. You can also pass in lambdas for more complex transformations.

Example:

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

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

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

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

{ "firstName": "David" }

Lambdas can also be used.

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

{ "_first_name": "David" }


107
108
109
# File 'lib/jbuilder.rb', line 107

def key_format!(*args)
  @key_formatter = KeyFormatter.new(*args)
end

#merge!(object) ⇒ Object

Merges hash, array, or Jbuilder instance into current builder.



276
277
278
279
# File 'lib/jbuilder.rb', line 276

def merge!(object)
  hash_or_array = ::Jbuilder === object ? object.attributes! : object
  @attributes = _merge_values(@attributes, _format_keys(hash_or_array))
end

#nil!Object Also known as: null!

Returns the nil JSON.



264
265
266
# File 'lib/jbuilder.rb', line 264

def nil!
  @attributes = nil
end

#set!(key, value = BLANK, *args, &block) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/jbuilder.rb', line 36

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": "[email protected]" } }
    _merge_block(key){ extract! value, *args }
  end

  _set_value key, result
end

#target!Object

Encodes the current builder as JSON.



282
283
284
# File 'lib/jbuilder.rb', line 282

def target!
  @attributes.to_json
end