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

Direct Known Subclasses

Manifest

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:



22
23
24
25
26
27
28
29
30
# File 'lib/serializer/serializable.rb', line 22

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

Class Method Details

.deep_diff(*hashes) ⇒ OrderedHash

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:

  • (OrderedHash)

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

See Also:



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

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

Instance Method Details

#array_to_hash(array, summary = false) ⇒ OrderedHash

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:

  • (OrderedHash)

    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



83
84
85
86
87
88
89
90
91
# File 'lib/serializer/serializable.rb', line 83

def array_to_hash(array,summary=false)
  item_hash = OrderedHash.new
  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) ⇒ OrderedHash

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

Parameters:

Returns:

  • (OrderedHash)

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



122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/serializer/serializable.rb', line 122

def diff(other)
  raise "Cannot compare different classes" if self.class != other.class
  left = other.to_hash
  right = self.to_hash
  if self.key.nil? or other.key.nil?
    ltag = :old
    rtag = :new
  else
    ltag = other.key
    rtag = self.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



73
74
75
76
# File 'lib/serializer/serializable.rb', line 73

def key
  return self.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:



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/serializer/serializable.rb', line 58

def key_name
  if not 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

#summaryOrderedHash

Returns Calls to_hash(summary=true).

Returns:



115
116
117
# File 'lib/serializer/serializable.rb', line 115

def summary
  self.to_hash(summary=true)
end

#to_hash(summary = false) ⇒ OrderedHash

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

Parameters:

  • summary (Boolean) (defaults to: false)

    Controls the depth and detail of recursion

Returns:

  • (OrderedHash)

    Recursively generate an OrderedHash containing the object’s properties



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/serializer/serializable.rb', line 96

def to_hash(summary=false)
  oh = OrderedHash.new
  vars = summary ? variables.select{|v| summary_fields.include?(v.name)} : variables
  vars.each do |variable|
    key = variable.options[:tag] || variable.name.to_s
    value = self.send(variable.name)
    case value
      when Array
        oh[key] = array_to_hash(value,summary)
      when Serializable
        oh[key] = value.to_hash
      else
        oh[key] = 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



165
166
167
168
# File 'lib/serializer/serializable.rb', line 165

def to_json(summary=false)
  hash=self.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



172
173
174
# File 'lib/serializer/serializable.rb', line 172

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

#variable_namesArray

Returns Extract the names of the variables.

Returns:

  • (Array)

    Extract the names of the variables



49
50
51
# File 'lib/serializer/serializable.rb', line 49

def variable_names
  variables.collect { |variable| variable.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



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/serializer/serializable.rb', line 34

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