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/dependency_tracker.rb

Direct Known Subclasses

JbuilderTemplate

Defined Under Namespace

Modules: DependencyTrackerMethods Classes: ArrayError, Blank, KeyFormatter, MergeError, NullError, Railtie

Constant Summary collapse

BLANK =
Blank.new
NON_ENUMERABLES =
[ ::Struct, ::OpenStruct ].to_set
DependencyTracker =
Class.new(dependency_tracker::ERBTracker)
@@key_formatter =
nil
@@ignore_nil =
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



12
13
14
15
16
17
18
19
# File 'lib/jbuilder.rb', line 12

def initialize(options = {})
  @attributes = {}

  @key_formatter = options.fetch(:key_formatter){ @@key_formatter ? @@key_formatter.clone : nil}
  @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil)

  yield self if ::Kernel.block_given?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/jbuilder.rb', line 64

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

Class Method Details

.encode(*args, &block) ⇒ Object

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



22
23
24
# File 'lib/jbuilder.rb', line 22

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.



129
130
131
# File 'lib/jbuilder.rb', line 129

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.



105
106
107
# File 'lib/jbuilder.rb', line 105

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

Instance Method Details

#array!(collection = [], *attributes) ⇒ 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 } ]

If you are using Ruby 1.9+, 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]


184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/jbuilder.rb', line 184

def array!(collection = [], *attributes)
  array = if collection.nil?
    []
  elsif ::Kernel.block_given?
    _map_collection(collection, &::Proc.new)
  elsif attributes.any?
    _map_collection(collection) { |element| extract! element, *attributes }
  else
    collection.to_a
  end

  merge! array
end

#attributes!Object

Returns the attributes of the current builder.



239
240
241
# File 'lib/jbuilder.rb', line 239

def attributes!
  @attributes
end

#call(object, *attributes) ⇒ Object



223
224
225
226
227
228
229
# File 'lib/jbuilder.rb', line 223

def call(object, *attributes)
  if ::Kernel.block_given?
    array! object, &::Proc.new
  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


149
150
151
152
# File 'lib/jbuilder.rb', line 149

def child!
  @attributes = [] unless ::Array === @attributes
  @attributes << _scope{ yield self }
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)


215
216
217
218
219
220
221
# File 'lib/jbuilder.rb', line 215

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

{}


124
125
126
# File 'lib/jbuilder.rb', line 124

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" }


100
101
102
# File 'lib/jbuilder.rb', line 100

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

#merge!(hash_or_array) ⇒ Object

Merges hash or array into current builder.



244
245
246
# File 'lib/jbuilder.rb', line 244

def merge!(hash_or_array)
  @attributes = _merge_values(@attributes, hash_or_array)
end

#nil!Object Also known as: null!

Returns the nil JSON.



232
233
234
# File 'lib/jbuilder.rb', line 232

def nil!
  @attributes = nil
end

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



29
30
31
32
33
34
35
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
# File 'lib/jbuilder.rb', line 29

def set!(key, value = BLANK, *args)
  result = if ::Kernel.block_given?
    if !_blank?(value)
      # json.comments @post.comments { |comment| ... }
      # { "comments": [ { ... }, { ... } ] }
      _scope{ array! value, &::Proc.new }
    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": { ...  }
      value.attributes!
    else
      # json.age 32
      # { "age": 32 }
      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.



249
250
251
# File 'lib/jbuilder.rb', line 249

def target!
  @attributes.to_json
end