class Rabl::Builder
Constants
- SETTING_TYPES
Public Class Methods
Constructs a new rabl hash based on given object and options options = { :format => “json”, :root => true, :child_root => true,
:attributes, :node, :child, :glue, :extends }
# File lib/rabl/builder.rb, line 16 def initialize(options={}, &block) @options = options @_scope = options[:scope] @_view_path = options[:view_path] end
Public Instance Methods
Given an object and options, returns the hash representation build(@user, :format => “json”, :attributes => { … }, :root_name => “user”)
# File lib/rabl/builder.rb, line 24 def build(object, options={}) @_object = object cache_results do compile_hash(options) end end
Protected Instance Methods
Indicates an attribute or method should be included in the json output attribute :foo, :as => “bar” attribute :foo, :as => “bar”, :if => lambda { |m| m.foo }
# File lib/rabl/builder.rb, line 116 def attribute(name, options={}) if @_object && attribute_present?(name) && resolve_condition(options) attribute = data_object_attribute(name) name = (options[:as] || name).to_sym @_result[name] = attribute end end
Evaluate conditions given a symbol to evaluate
# File lib/rabl/builder.rb, line 173 def call_condition_proc(condition, object, &blk) blk = lambda { |v| v } unless block_given? if condition.respond_to?(:call) # condition is a block to pass to the block blk.call(condition.call(object)) elsif condition.is_a?(Symbol) && object.respond_to?(condition) # condition is a property of the object blk.call(object.send(condition)) else false end end
Creates a child node that is included in json output child(@user) { attribute :full_name } child(@user => :person) { … } child(@users => :people) { … }
# File lib/rabl/builder.rb, line 143 def child(data, options={}, &block) return false unless data.present? && resolve_condition(options) name = is_name_value?(options[:root]) ? options[:root] : data_name(data) object = data_object(data) include_root = is_collection?(object) && options.fetch(:object_root, @options[:child_root]) # child @users engine_options = @options.slice(:child_root).merge(:root => include_root) engine_options.merge!(:object_root_name => options[:object_root]) if is_name_value?(options[:object_root]) object = { object => name } if data.respond_to?(:each_pair) && object # child :users => :people @_result[name.to_sym] = self.object_to_hash(object, engine_options, &block) end
Returns a hash representation of the data object #compile_hash(:root_name => false) #compile_hash(:root_name => “user”)
# File lib/rabl/builder.rb, line 37 def compile_hash(options={}) @_result = {} update_settings(:extends) update_attributes update_settings(:node) update_settings(:child) update_settings(:glue) wrap_result(options[:root_name]) replace_nil_values if Rabl.configuration.replace_nil_values_with_empty_strings replace_empty_string_values if Rabl.configuration.replace_empty_string_values_with_nil_values remove_nil_values if Rabl.configuration.exclude_nil_values # Return Results @_root_name ? { @_root_name => @_result } : @_result end
# File lib/rabl/builder.rb, line 74 def deep_replace_empty_string_values(hash) hash.inject({}) do |hsh, (k, v)| hsh[k] = if v.is_a?(Hash) deep_replace_empty_string_values(v) else (!v.nil? && v != "") ? v : nil end hsh end end
# File lib/rabl/builder.rb, line 59 def deep_replace_nil_values(hash) hash.inject({}) do |hsh, (k, v)| hsh[k] = if v.is_a?(Hash) deep_replace_nil_values(v) else v.nil? ? '' : v end hsh end end
Extends an existing rabl template with additional attributes in the block extends(“users/show”) { attribute :full_name }
# File lib/rabl/builder.rb, line 165 def extends(file, options={}, &block) return unless resolve_condition(options) options = @options.slice(:child_root).merge(:object => @_object).merge(options) result = self.partial(file, options, &block) @_result.merge!(result) if result.is_a?(Hash) end
Glues data from a child node to the json_output glue(@user) { attribute :full_name => :user_full_name }
# File lib/rabl/builder.rb, line 156 def glue(data, options={}, &block) return false unless data.present? && resolve_condition(options) object = data_object(data) glued_attributes = self.object_to_hash(object, :root => false, &block) @_result.merge!(glued_attributes) if glued_attributes end
Creates an arbitrary node that is included in the json output node(:foo) { “bar” } node(:foo, :if => lambda { |m| m.foo.present? }) { “bar” }
# File lib/rabl/builder.rb, line 128 def node(name, options={}, &block) return unless resolve_condition(options) result = block.call(@_object) if name.present? @_result[name.to_sym] = result elsif result.respond_to?(:each_pair) # merge hash into root hash @_result.merge!(result) end end
# File lib/rabl/builder.rb, line 85 def remove_nil_values @_result = @_result.inject({}) do |hash, (k, v)| hash[k] = v unless v.nil? hash end end
# File lib/rabl/builder.rb, line 70 def replace_empty_string_values @_result = deep_replace_empty_string_values(@_result) end
# File lib/rabl/builder.rb, line 55 def replace_nil_values @_result = deep_replace_nil_values(@_result) end
#resolve_condition(:if => true) => true #resolve_condition(:if => lambda { |m| false }) => false #resolve_condition(:unless => lambda { |m| true }) => true
# File lib/rabl/builder.rb, line 189 def resolve_condition(options) return true if options[:if].nil? && options[:unless].nil? result = nil if options.has_key?(:if) result = options[:if] == true || call_condition_proc(options[:if], @_object) end if options.has_key?(:unless) inverse_proc = lambda { |r| !r } result = options[:unless] == false || call_condition_proc(options[:unless], @_object, &inverse_proc) end result end
# File lib/rabl/builder.rb, line 107 def update_attributes @options[:attributes].each_pair do |attribute, settings| attribute(attribute, settings) end if @options.has_key?(:attributes) end
# File lib/rabl/builder.rb, line 100 def update_settings(type) settings_type = SETTING_TYPES[type] @options[type].each do |settings| send(type, settings[settings_type], settings[:options], &settings[:block]) end if @options.has_key?(type) end
# File lib/rabl/builder.rb, line 92 def wrap_result(root_name) if root_name.present? @_root_name = root_name else # no root @_root_name = nil end end
Private Instance Methods
Checks if an attribute is present. If not, check if the configuration specifies that this is an error attribute_present?(created_at) => true
# File lib/rabl/builder.rb, line 206 def attribute_present?(name) if @_object.respond_to?(name) return true elsif Rabl.configuration.raise_on_missing_attribute raise "Failed to render missing attribute #{name}" else return false end end
Caches the results of the block based on object cache_key #cache_results { #compile_hash(options) }
# File lib/rabl/builder.rb, line 225 def cache_results(&block) if template_cache_configured? && Rabl.configuration.cache_all_output && @_object.respond_to?(:cache_key) result_cache_key = [@_object, @options[:root_name], @options[:format]] fetch_result_from_cache(result_cache_key, &block) else # skip cache yield end end
Returns a guess at the format in this scope #request_format => “xml”
# File lib/rabl/builder.rb, line 218 def request_format format = @options[:format] format && format != "hash" ? format : 'json' end