Class: Jbuilder

Inherits:
BlankSlate
  • Object
show all
Defined in:
lib/jbuilder.rb

Direct Known Subclasses

JbuilderTemplate

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeJbuilder



16
17
18
# File 'lib/jbuilder.rb', line 16

def initialize
  @attributes = ActiveSupport::OrderedHash.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object (private)



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/jbuilder.rb', line 120

def method_missing(method, *args)
  case
  # json.comments @post.comments { |json, comment| ... }
  # { "comments": [ { ... }, { ... } ] }
  when args.one? && block_given?
    _yield_iteration(method, args.first) { |child, element| yield child, element }

  # json.age 32
  # { "age": 32 }
  when args.length == 1
    set! method, args.first

  # json.comments { |json| ... }
  # { "comments": ... }
  when args.empty? && block_given?
    _yield_nesting(method) { |jbuilder| yield jbuilder }
  
  # json.comments(@post.comments, :content, :created_at)
  # { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] }
  when args.many? && args.first.is_a?(Enumerable)
    _inline_nesting method, args.first, args.from(1)

  # json.author @post.creator, :name, :email_address
  # { "author": { "name": "David", "email_address": "[email protected]" } }
  when args.many?
    _inline_extract method, args.first, args.from(1)
  end
end

Class Method Details

.encodeObject

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



9
10
11
# File 'lib/jbuilder.rb', line 9

def self.encode
  new._tap { |jbuilder| yield jbuilder }.target!
end

Instance Method Details

#array!(collection) ⇒ 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 |json, 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) { |json, 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 |json, person|
  json.name person.name
  json.age calculate_age(person.birthday)
end  

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


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

def array!(collection)
  @attributes = [] and return if collection.empty?
  
  collection.each do |element|
    child! do |child|
      yield child, element
    end
  end
end

#attributes!Object

Returns the attributes of the current builder.



109
110
111
# File 'lib/jbuilder.rb', line 109

def attributes!
  @attributes
end

#call(*args) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/jbuilder.rb', line 98

def call(*args)
  case
  when args.one?
    array!(args.first) { |json, element| yield json, element }
  when args.many?
    extract!(*args)
  end
end

#child!Object

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

Example:

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

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

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

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


41
42
43
44
# File 'lib/jbuilder.rb', line 41

def child!
  @attributes = [] unless @attributes.is_a? Array
  @attributes << _new_instance._tap { |jbuilder| yield jbuilder }.attributes!
end

#extract!(object, *attributes) ⇒ Object

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

Example:

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

{ "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.(@person, :name, :age)


91
92
93
94
95
# File 'lib/jbuilder.rb', line 91

def extract!(object, *attributes)
  attributes.each do |attribute|
    __send__ attribute, object.send(attribute)
  end
end

#set!(key, value) ⇒ Object

Dynamically set a key value pair.



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

def set!(key, value)
  @attributes[key] = value
end

#target!Object

Encodes the current builder as JSON.



114
115
116
# File 'lib/jbuilder.rb', line 114

def target!
  ActiveSupport::JSON.encode @attributes
end