Class: Hoodoo::Presenters::Object

Inherits:
Field
  • Object
show all
Includes:
BaseDSL
Defined in:
lib/hoodoo/presenters/types/object.rb

Overview

A JSON Object schema member.

Instance Attribute Summary collapse

Attributes inherited from Field

#default, #name, #required

Instance Method Summary collapse

Methods included from BaseDSL

#array, #boolean, #date, #datetime, #decimal, #enum, #float, #hash, #integer, #internationalised, #is_internationalised?, #object, #resource, #string, #tags, #text, #type, #uuid

Methods inherited from Field

#full_path, #has_default?

Constructor Details

#initialize(name = nil, options = {}) ⇒ Object

Initialize an Object instance with the appropriate name and options.

name

The JSON key.

options

A Hash of options, e.g. :required => true.



20
21
22
23
24
25
# File 'lib/hoodoo/presenters/types/object.rb', line 20

def initialize( name = nil, options = {} )
  super( name, options )

  @properties        = {}
  @internationalised = false
end

Instance Attribute Details

#propertiesObject

The properties of this object; a Hash of Field instances keyed by field name.



13
14
15
# File 'lib/hoodoo/presenters/types/object.rb', line 13

def properties
  @properties
end

Instance Method Details

#render(data, target) ⇒ Object

Render inbound data into a target hash according to the schema, applying defaults where defined for fields with no value supplied in the inbound data.

data

Inbound data to render.

target

For internal callers only in theory. The target hash into which rendering should occur. This may then be merged into outer level hashes as part of nested items defined in the schema.



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/hoodoo/presenters/types/object.rb', line 70

def render( data, target )

  # In an simple field, e.g. a text field, then whether or not it has
  # a default, should someone give a value of "nil" we expect that field
  # to be rendered in output with the explicitly provided "nil" value.
  # We thus apply the same to objects. A field with an associated object,
  # if rendered with an explicit "nil", renders as just that.
  #
  return super( nil, target ) unless data.is_a?( ::Hash ) # nil or invalid

  have_rendered_something = false

  @properties.each do | name, property |
    name    = name.to_s
    has_key = data.has_key?( name )

    next unless has_key || property.has_default?()

    have_rendered_something = true
    property.render( has_key ? data[ name ] : property.default, target )
  end

  # If someone passes an empty object for a field and the object schema
  # includes no default values, then the above code would render nothing
  # as no properties have associated keys in the input data, and none of
  # them have default values either. Make sure we render the field for
  # this object with the associated empty object given by the input data
  # in such cases.
  #
  super( {}, target ) unless have_rendered_something

end

#validate(data, path = '') ⇒ Object

Check if data is a valid Object and return a Hoodoo::Errors instance with zero (valid) or more (has validation problems) errors inside.

data

Data to check (and check nested properties therein). Expected to be nil (unless field is required) or a Hash.

path

For internal callers only in theory - the human-readable nesting path to this “level”, as an array. Omitted at the top level. In :errors => { :foo => { … } }, validation of “:foo” would be at path “[ :errors ]”. Validation of the contents of the object at “:foo” would be under “[ :errors, :foo ]”.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/hoodoo/presenters/types/object.rb', line 39

def validate( data, path = '' )
  errors = super( data, path )
  return errors if !@required and data.nil? # If there are existing errors, we carry on and validate internally too

  if ! data.nil? && ! data.is_a?( ::Hash )
    errors.add_error(
      'generic.invalid_object',
      :message   => "Field `#{ full_path( path ) }` is an invalid object",
      :reference => { :field_name => full_path( path ) }
    )
  end

  @properties.each do | name, property |
    rdata = ( data.is_a?( ::Hash ) && data.has_key?( name ) ) ? data[ name ] : nil
    errors.merge!( property.validate( rdata, full_path( path ) ) )
  end

  errors
end

#walk(&block) ⇒ Object

Invoke a given block, passing this item; call recursively for any defined sub-fields too. See Hoodoo::Presenters::Base#walk for why.

&block

Mandatory block, which is passed ‘self’ when called.



108
109
110
111
112
113
114
# File 'lib/hoodoo/presenters/types/object.rb', line 108

def walk( &block )
  block.call( self )

  @properties.each do | name, property |
    property.walk( &block )
  end unless @properties.nil?
end