Class: Jbuilder
- Inherits:
- ActiveSupport::BasicObject
- Defined in:
- lib/jbuilder.rb
Direct Known Subclasses
Defined Under Namespace
Classes: KeyFormatter
Constant Summary collapse
- @@key_formatter =
KeyFormatter.new
Class Method Summary collapse
-
.encode(*args) {|jbuilder| ... } ⇒ Object
Yields a builder and automatically turns the result into a JSON string.
-
.key_format(*args) ⇒ Object
Same as the instance method key_format! except sets the default.
Instance Method Summary collapse
-
#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.
-
#attributes! ⇒ Object
Returns the attributes of the current builder.
- #call(object = nil, *attributes) ⇒ Object
-
#child! ⇒ Object
Turns the current element into an array and yields a builder to add a hash.
-
#extract!(object, *attributes) ⇒ Object
Extracts the mentioned attributes or hash elements from the passed object and turns them into attributes of the JSON.
-
#initialize(key_formatter = @@key_formatter.clone) ⇒ Jbuilder
constructor
A new instance of Jbuilder.
-
#key_format!(*args) ⇒ Object
Specifies formatting to be applied to the key.
-
#set!(key, value = nil) ⇒ Object
Dynamically set a key value pair.
-
#target! ⇒ Object
Encodes the current builder as JSON.
Constructor Details
#initialize(key_formatter = @@key_formatter.clone) ⇒ Jbuilder
Returns a new instance of Jbuilder.
49 50 51 52 |
# File 'lib/jbuilder.rb', line 49 def initialize(key_formatter = @@key_formatter.clone) @attributes = ::ActiveSupport::OrderedHash.new @key_formatter = key_formatter end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, value = nil, *args) ⇒ Object (private)
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/jbuilder.rb', line 223 def method_missing(method, value = nil, *args) result = if ::Kernel.block_given? if value # json.comments @post.comments { |comment| ... } # { "comments": [ { ... }, { ... } ] } _map_collection(value) { |element| if ::Proc.new.arity == 2 then yield self, element else yield element end } else # json.comments { ... } # { "comments": ... } _scope { yield self } end else if 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 else if value.respond_to?(:each) # json.comments(@post.comments, :content, :created_at) # { "comments": [ { "content": "hello", "created_at": "..." }, { "content": "world", "created_at": "..." } ] } _map_collection(value) do |element| args.each do |attribute| _set_value attribute, element.send(attribute) end end else # json.author @post.creator, :name, :email_address # { "author": { "name": "David", "email_address": "[email protected]" } } _scope { extract! value, *args } end end end _set_value method, result end |
Class Method Details
.encode(*args) {|jbuilder| ... } ⇒ Object
Yields a builder and automatically turns the result into a JSON string
41 42 43 44 45 |
# File 'lib/jbuilder.rb', line 41 def self.encode(*args) jbuilder = new(*args) yield jbuilder jbuilder.target! end |
.key_format(*args) ⇒ Object
Same as the instance method key_format! except sets the default.
111 112 113 |
# File 'lib/jbuilder.rb', line 111 def self.key_format(*args) @@key_formatter = KeyFormatter.new(*args) 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 |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]
166 167 168 169 170 171 172 |
# File 'lib/jbuilder.rb', line 166 def array!(collection) @attributes = if ::Kernel::block_given? _map_collection(collection) { |element| if ::Proc.new.arity == 2 then yield self, element else yield element end } else collection end end |
#attributes! ⇒ Object
Returns the attributes of the current builder.
208 209 210 |
# File 'lib/jbuilder.rb', line 208 def attributes! @attributes end |
#call(object = nil, *attributes) ⇒ Object
199 200 201 202 203 204 205 |
# File 'lib/jbuilder.rb', line 199 def call(object = nil, *attributes) if attributes.empty? 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
131 132 133 134 |
# File 'lib/jbuilder.rb', line 131 def child! @attributes = [] unless @attributes.is_a? ::Array @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 }
If you are using Ruby 1.9+, you can use the call syntax instead of an explicit extract! call:
json.(@person, :name, :age)
191 192 193 194 195 196 197 |
# File 'lib/jbuilder.rb', line 191 def extract!(object, *attributes) if object.is_a?(::Hash) attributes.each {|attribute| _set_value attribute, object.send(:fetch, attribute)} else attributes.each {|attribute| _set_value attribute, object.send(attribute)} end 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. 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" }
106 107 108 |
# File 'lib/jbuilder.rb', line 106 def key_format!(*args) @key_formatter = KeyFormatter.new(*args) end |
#set!(key, value = nil) ⇒ Object
Dynamically set a key value pair.
Example:
json.set!(:each, "stuff")
{ "each": "stuff" }
You can also pass a block for nested attributes
json.set!(:author) do
json.name "David"
json.age 32
end
{ "author": { "name": "David", "age": 32 } }
70 71 72 73 74 75 76 |
# File 'lib/jbuilder.rb', line 70 def set!(key, value = nil) if ::Kernel::block_given? _set_value(key, _scope { yield self }) else _set_value(key, value) end end |
#target! ⇒ Object
Encodes the current builder as JSON.
213 214 215 |
# File 'lib/jbuilder.rb', line 213 def target! ::MultiJson.encode @attributes end |