Yields a builder and automatically turns the result into a JSON string
# File lib/jbuilder.rb, line 54 def self.encode(*args, &block) new(*args, &block).target! end
Same as instance method ::ignore_nil! except sets the default.
# File lib/jbuilder.rb, line 169 def self.ignore_nil(value = true) @@ignore_nil = value end
Same as the instance method ::key_format! except sets the default.
# File lib/jbuilder.rb, line 145 def self.key_format(*args) @@key_formatter = KeyFormatter.new(*args) end
# File lib/jbuilder.rb, line 61 def initialize(*args, &block) @attributes = ::ActiveSupport::OrderedHash.new options = args.extract_options! @key_formatter = options.fetch(:key_formatter, @@key_formatter.clone) @ignore_nil = options.fetch(:ignore_nil, @@ignore_nil) yield self if block end
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]
# File lib/jbuilder.rb, line 224 def array!(collection, *attributes, &block) @attributes = if block && block.arity == 2 _two_arguments_map_collection(collection, &block) elsif block _map_collection(collection, &block) elsif attributes.any? _map_collection(collection) { |element| extract! element, *attributes } else collection end end
Returns the attributes of the current builder.
# File lib/jbuilder.rb, line 277 def attributes! @attributes end
# File lib/jbuilder.rb, line 261 def call(object, *attributes, &block) if block array! object, &block else extract! object, *attributes end end
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
# File lib/jbuilder.rb, line 189 def child! @attributes = [] unless ::Array === @attributes @attributes << _scope { yield self } end
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)
# File lib/jbuilder.rb, line 253 def extract!(object, *attributes) if ::Hash === object _extract_hash_values(object, *attributes) else _extract_method_values(object, *attributes) end end
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 {}
# File lib/jbuilder.rb, line 164 def ignore_nil!(value = true) @ignore_nil = value end
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" }
# File lib/jbuilder.rb, line 140 def key_format!(*args) @key_formatter = KeyFormatter.new(*args) end
Returns the nil JSON.
# File lib/jbuilder.rb, line 270 def nil! @attributes = nil end
# File lib/jbuilder.rb, line 72 def set!(key, value = BLANK, *args, &block) result = if block if BLANK != value # json.comments @post.comments { |comment| ... } # { "comments": [ { ... }, { ... } ] } _scope{ array! value, &block } else # json.comments { ... } # { "comments": ... } _scope { 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 value.respond_to?(:map) # 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" } } _scope { extract! value, *args } end _set_value key, result end
Encodes the current builder as JSON.
# File lib/jbuilder.rb, line 282 def target! ::MultiJson.dump @attributes end
# File lib/jbuilder.rb, line 288 def _extract_hash_values(object, *attributes) attributes.each{ |key| _set_value key, object.fetch(key) } end
# File lib/jbuilder.rb, line 292 def _extract_method_values(object, *attributes) attributes.each do |method_name| unless object.respond_to?(method_name) message = "Private method #{method_name.inspect} was used to " + 'extract value. This will be an error in future versions of Jbuilder' end _set_value method_name, object.send(method_name) ::ActiveSupport::Deprecation.warn message if message end end
# File lib/jbuilder.rb, line 311 def _map_collection(collection) return [] if collection.nil? collection.map do |element| _scope { yield element } end end
# File lib/jbuilder.rb, line 328 def _merge(hash_or_array) if ::Array === hash_or_array @attributes = [] unless ::Array === @attributes @attributes.concat hash_or_array else @attributes.update hash_or_array end end
# File lib/jbuilder.rb, line 319 def _scope parent_attributes, parent_formatter = @attributes, @key_formatter @attributes = ::ActiveSupport::OrderedHash.new yield @attributes ensure @attributes, @key_formatter = parent_attributes, parent_formatter end
# File lib/jbuilder.rb, line 304 def _set_value(key, value) raise NullError, key if @attributes.nil? unless @ignore_nil && value.nil? @attributes[@key_formatter.format(key)] = value end end
# File lib/jbuilder.rb, line 337 def _two_arguments_map_collection(collection, &block) message = "Passing jbuilder object to block is " "deprecated and will be removed soon." if block.respond_to?(:parameters) arguments = block.parameters.map(&:last) actual = "|#{arguments.drop(1) * ', '}|" deprecated = "|#{arguments * ', '}|" message += "\nUse #{actual} instead of #{deprecated} as block arguments" end ::ActiveSupport::Deprecation.warn message, ::Kernel.caller(5) _map_collection(collection){ |element| block[self, element] } end