Module: SchemaTools::Modules::Hash

Included in:
Hash
Defined in:
lib/schema_tools/modules/hash.rb

Instance Method Summary collapse

Instance Method Details

#from_schema(obj, opts = {}) ⇒ Hash{String=>{String=>Mixed}}

Create a Hash with the available (api)object attributes defined in the according schema properties. This is the meat of the object-to-api-markup workflow

Example

obj = Invoice.new(:title =>'hello world', :number=>'4711')

obj_hash = SchemaTools::Hash.from_schema(obj)
 => { 'invoice' =>{'title'=>'hello world', 'number'=>'4711' } }

obj_hash = Schema.to_hash_from_schema(obj, fields: ['title'])
 => { 'invoice' =>{'title'=>'hello world' } }

obj_hash = Schema.to_hash_from_schema(obj, class_name: :document)
 => { 'document' =>{'title'=>'hello world' } }

a lowercase underscored name and it MUST have an existing schema file. Use it to override the default, which is obj.class.name properties are used.

Parameters:

  • obj (Object)

    which is returned as hash

  • opts (Hash{Symbol=>Mixed}) (defaults to: {})

    additional options

Returns:

  • (Hash{String=>{String=>Mixed}})

    The object as hash: { ‘invoice’ => {‘title’=>‘hello world’, ‘number’=>‘4711’ } }



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/schema_tools/modules/hash.rb', line 39

def from_schema(obj, opts={})
  fields = opts[:fields]
  # get objects class name without inheritance
  real_class_name = obj.class.name.split('::').last.underscore
  class_name = opts[:class_name] || real_class_name

  data = {}
  # get schema
  schema = SchemaTools::Reader.read(class_name, opts[:path])
  # iterate over the defined schema fields
  schema['properties'].each do |field, prop|
    next if fields && !fields.include?(field)

    if prop['type'] == 'array'

      data[field] = [] # always set an empty array
      if obj.respond_to?( field ) && rel_objects = obj.send( field )
        rel_objects.each do |rel_obj|
          data[field] << if prop['properties'] && prop['properties']['$ref']
                            #got schema describing the objects
                            from_schema(rel_obj, opts)
                          else
                            rel_obj
                          end
        end
      end

    elsif prop['type'] == 'object' # a singular related object

      data[field] = nil # always set empty val
      if obj.respond_to?( field ) && rel_obj = obj.send( field )
        if prop['properties'] && prop['properties']['$ref']
          data[field] = from_schema(rel_obj, opts)
        else
          # NO recursion directly get values from related object. Does
          # NOT allow deeper nesting so you MUST define an own schema to be save
          data[field] = {}
          prop['properties'].each do |fld, prp|
            data[field][fld] = rel_obj.send(fld) if obj.respond_to?(field)
          end
        end
      end

    else # a simple field is only added if the object knows it
      data[field] = obj.send(field) if obj.respond_to?(field)
    end
  end
  hsh = { "#{class_name}" => data }
  #add links if present
  links = parse_links(obj, schema)
  links && hsh['links'] = links
  hsh
end

Parse the link section of the schema by replacing id in urls

Returns

<Array>
<nil>

no links present



97
98
99
100
101
102
103
104
105
# File 'lib/schema_tools/modules/hash.rb', line 97

def parse_links(obj, schema)
  links = []
  schema['links'] && schema['links'].each do |link|
    links << { 'rel' => link['rel'], 'href' => link['href'].gsub(/\{id\}/, "#{obj.id}") }
  end
  links.uniq
  # return links only if not empty
  links.empty? ? nil : links
end