Class: Serializer::Serializable

Inherits:
Object
  • Object
show all
Includes:
HappyMapper
Defined in:
lib/serializer/serializable.rb

Overview

Note:

Copyright © 2012 by The Board of Trustees of the Leland Stanford Junior University. All rights reserved. See LICENSE for details.

Some utility methods to faciliate serialization of data fields to Hash, JSON, or YAML shared by all subclasses. This class assumes that HappyMapper is used for declaration of fields to be serialized.

Data Model

  • Serializable = utility methods to faciliate serialization to Hash, JSON, or YAML

    • Manifest = adds methods for marshalling/unmarshalling data to a persistent XML file format

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Serializable

A flexible initializer based on the DataMapper “create factory” design pattern.

Parameters:

  • opts (Hash<Symbol,Object>) (defaults to: {})

    a hash containing any number of symbol => value pairs. The symbols should correspond to attributes declared using HappyMapper syntax

See Also:



20
21
22
23
24
25
# File 'lib/serializer/serializable.rb', line 20

def initialize(opts = {})
  opts.each do |key, value|
    raise "#{key} is not a variable name in #{self.class.name}" unless variable_names.include?(key.to_s) || key == :test
    instance_variable_set("@#{key}", value)
  end
end

Class Method Details

.deep_diff(*hashes) ⇒ Hash

Returns Generate a hash containing the differences between two hashes (recursively descend parallel trees of hashes).

Parameters:

  • hashes (Array<Hash>)

    The hashes to be compared, with optional name tags

Returns:

  • (Hash)

    Generate a hash containing the differences between two hashes (recursively descend parallel trees of hashes)

See Also:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/serializer/serializable.rb', line 136

def self.deep_diff(*hashes)
  diff = {}
  case hashes.length
  when 4
    ltag, left, rtag, right = hashes
  when 2
    ltag = :left
    left = hashes[0]
    rtag = :right
    right = hashes[1]
  else
    raise ArgumentError, "wrong number of arguments (#{hashes.length} for 2 or 4)"
  end
  (left.keys | right.keys).each do |k|
    if left[k] != right[k]
      diff[k] = if left[k].is_a?(Hash) && right[k].is_a?(Hash)
                  deep_diff(ltag, left[k], rtag, right[k])
                else
                  Hash.[](ltag, left[k], rtag, right[k])
                end
    end
  end
  diff
end

Instance Method Details

#array_to_hash(array, summary = false) ⇒ Hash

Returns Generate a hash from an array of objects. If the array member has a field tagged as a key, that field will be used as the hash.key. Otherwise the index position of the array member will be used as the key.

Parameters:

  • array (Array)

    The array to be converted to a hash

Returns:

  • (Hash)

    Generate a hash from an array of objects. If the array member has a field tagged as a key, that field will be used as the hash.key. Otherwise the index position of the array member will be used as the key



78
79
80
81
82
83
84
85
86
# File 'lib/serializer/serializable.rb', line 78

def array_to_hash(array, summary = false)
  item_hash = {}
  array.each_index do |index|
    item = array[index]
    ikey = item.respond_to?(:key) && item.key ? item.key : index
    item_hash[ikey] = item.respond_to?(:to_hash) ? item.to_hash(summary) : item
  end
  item_hash
end

#diff(other) ⇒ Hash

Returns Generate a hash containing the differences between two objects of the same type.

Parameters:

Returns:

  • (Hash)

    Generate a hash containing the differences between two objects of the same type



117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/serializer/serializable.rb', line 117

def diff(other)
  raise "Cannot compare different classes" if self.class != other.class
  left = other.to_hash
  right = to_hash
  if key.nil? || other.key.nil?
    ltag = :old
    rtag = :new
  else
    ltag = other.key
    rtag = key
  end
  Serializable.deep_diff(ltag, left, rtag, right)
end

#keyString

Returns For the current object instance, return the string to use as a hash key.

Returns:

  • (String)

    For the current object instance, return the string to use as a hash key



68
69
70
71
# File 'lib/serializer/serializable.rb', line 68

def key
  return send(key_name) if key_name
  nil
end

#key_nameString

Returns Determine which attribute was marked as an object instance key. Keys are indicated by option :key=true when declaring the object’s variables. This follows the same convention as used by DataMapper.

Returns:

  • (String)

    Determine which attribute was marked as an object instance key. Keys are indicated by option :key=true when declaring the object’s variables. This follows the same convention as used by DataMapper

See Also:



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/serializer/serializable.rb', line 53

def key_name
  unless defined?(@key_name)
    @key_name = nil
    self.class.attributes.each do |attribute|
      if attribute.options[:key]
        @key_name = attribute.name
        break
      end
    end
  end
  @key_name
end

#summaryHash

Returns Calls to_hash(summary=true).

Returns:

  • (Hash)

    Calls to_hash(summary=true)



110
111
112
# File 'lib/serializer/serializable.rb', line 110

def summary
  to_hash(summary = true)
end

#to_hash(summary = false) ⇒ Hash

Returns Recursively generate an Hash containing the object’s properties.

Parameters:

  • summary (Boolean) (defaults to: false)

    Controls the depth and detail of recursion

Returns:

  • (Hash)

    Recursively generate an Hash containing the object’s properties



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/serializer/serializable.rb', line 91

def to_hash(summary = false)
  oh = {}
  vars = summary ? variables.select { |v| summary_fields.include?(v.name) } : variables
  vars.each do |variable|
    key = variable.name.to_s
    value = send(variable.name)
    oh[key] = case value
              when Array
                array_to_hash(value, summary)
              when Serializable
                value.to_hash
              else
                value
              end
  end
  oh
end

#to_json(summary = false) ⇒ String

Returns Generate JSON output from a hash of the object’s variables.

Returns:

  • (String)

    Generate JSON output from a hash of the object’s variables



163
164
165
166
# File 'lib/serializer/serializable.rb', line 163

def to_json(summary = false)
  hash = to_hash(summary)
  JSON.pretty_generate(hash)
end

#to_yaml(summary = false) ⇒ String

Returns Generate YAML output from a hash of the object’s variables.

Returns:

  • (String)

    Generate YAML output from a hash of the object’s variables



170
171
172
# File 'lib/serializer/serializable.rb', line 170

def to_yaml(summary = false)
  to_hash(summary).to_yaml
end

#variable_namesArray

Returns Extract the names of the variables.

Returns:

  • (Array)

    Extract the names of the variables



44
45
46
# File 'lib/serializer/serializable.rb', line 44

def variable_names
  variables.collect(&:name)
end

#variablesArray

Returns A list of HappyMapper xml attribute, element and text nodes declared for the class.

Returns:

  • (Array)

    A list of HappyMapper xml attribute, element and text nodes declared for the class



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/serializer/serializable.rb', line 29

def variables
  attributes = self.class.attributes
  elements   = self.class.elements
  attributes + elements
  # text_node enhancement added by unhappymapper, which is not being used
  # It enables elements having both attributes and a text value
  #text_node = []
  #if self.class.instance_variable_defined?("@text_node")
  #  text_node << self.class.instance_variable_get("@text_node")
  #end
  #attributes + elements + text_node
end