Class: Algebrick::Serializers::BenevolentToHash

Inherits:
AbstractToHash show all
Defined in:
lib/algebrick/serializers/benevolent_to_hash.rb,
lib/algebrick/serializers2/benevolent_to_hash.rb

Constant Summary

CANNOT =
Algebrick.atom

Instance Attribute Summary

Attributes inherited from AbstractToHash

#fields_key, #type_key

Instance Method Summary (collapse)

Methods inherited from AbstractToHash

#initialize

Methods included from TypeCheck

#Child!, #Child?, #Match!, #Match?, #Type!, #Type?, error

Constructor Details

This class inherits a constructor from Algebrick::Serializers::AbstractToHash

Instance Method Details

- (Boolean) can?(v) (private)

Returns:



131
132
133
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 131

def can?(v)
  v != CANNOT
end

- (Boolean) can_be?(type, object) (private)

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 33

def can_be?(type, object)
  Type! type, Module

  could? do
    cannot! unless object.is_a?(::Hash)
    cannot! unless object[type_key] || object[type_key.to_s]
    return object
  end

  could? { return can_be_atom? type, object }
  could? { return can_be_product_variant? type, object }

  return object if object.is_a?(type)

  cannot!
end

- (Boolean) can_be_atom?(type, object) (private)

Returns:



83
84
85
86
87
88
89
90
91
92
93
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 83

def can_be_atom?(type, object)
  Type! type, Module
  cannot! unless type.is_a?(Atom)
  cannot! unless object.is_a?(String) || object.is_a?(Symbol)

  last_name = type.name.split('::').last
  possible_representations = [type.name, last_name.downcase, underscore(last_name)]
  cannot! unless possible_representations.any? { |v| v == object.to_s }

  return type_key => type.name
end

- (Boolean) can_be_product?(type, object) (private)

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 95

def can_be_product?(type, object)
  Type! type, Module
  could? do
    cannot! unless object.is_a?(::Array) && !type.field_names?
    cannot! unless type.fields.size == object.size

    fields = many_can_by? type.fields.zip(object)
    return { type_key => type.name, fields_key => fields }
  end

  could? do
    cannot! unless object.is_a?(::Hash) && type.field_names?

    candidates = type.field_names.map do |field_name|
      v1 = object.fetch(field_name, CANNOT)
      v2 = object.fetch(field_name.to_s, CANNOT)
      (v = [v1, v2].find { |v| v != CANNOT }) or cannot!
    end

    values = many_can_by? type.fields.zip(candidates)

    fields = type.field_names.zip(values).
        each_with_object({}) { |(name, value), fields| fields[name] = value }

    return { type_key => type.name }.update(fields)
  end

  cannot!
end

- (Boolean) can_be_product_variant?(type, object) (private)

Returns:



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
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 56

def can_be_product_variant?(type, object)
  Type! type, Module
  cannot! unless type.is_a? ProductVariant

  if type.variants
    self_variant   = type.variants.find { |v| v == type }
    other_variants = type.variants - [self_variant]
    possibilities  = [
        *other_variants.map { |v| could? { can_be? v, object } },
        could? do
          cannot! unless self_variant
          can_be_atom? self_variant, object
        end,
        could? do
          cannot! unless self_variant
          can_be_product? self_variant, object
        end
    ].select { |v| can? v }

    cannot! if possibilities.empty?
    raise "multiple options #{possibilities}" if possibilities.size > 1
    possibilities.first
  else
    can_be_product? type, object
  end
end

- (Object) cannot! (private)



135
136
137
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 135

def cannot!
  throw CANNOT, CANNOT
end

- (Boolean) could? (private)

Returns:



125
126
127
128
129
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 125

def could?
  catch CANNOT do
    yield
  end
end

- (Object) dump(object, options = {})



18
19
20
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 18

def dump(object, options = {})
  object
end

- (Object) load(object, options = {})



22
23
24
25
26
27
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 22

def load(object, options = {})
  expected_type = Type! options[:expected_type], Module
  could? { can_be? expected_type, object }.tap do |v|
    raise "type mismatch #{object} is not #{expected_type} " unless can? v
  end
end

- (Boolean) many_can_by?(hash) (private)

Returns:



50
51
52
53
54
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 50

def many_can_by?(hash)
  hash.map do |type, value|
    can_be? type, value
  end
end

- (Object) underscore(string) (private)



139
140
141
# File 'lib/algebrick/serializers/benevolent_to_hash.rb', line 139

def underscore(string)
  string[0].downcase + string[1..-1].gsub(/([A-Z])/) { |m| '_' + m.downcase }
end