Class: Typed::Hash

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/typed/hash.rb

Constant Summary collapse

DEFAULT_OPTIONS =
{
  :schema => true,
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Hash

Returns a new instance of Hash.



13
14
15
16
17
18
19
20
# File 'lib/typed/hash.rb', line 13

def initialize(options = {})
  @hash    = ActiveSupport::OrderedHash.new
  @options = DEFAULT_OPTIONS.merge(options.must(::Hash))
  @schema  = Schema.new
  @default = Default.new(self)
  @changes = Changes.new
  @events  = Events.new
end

Instance Attribute Details

#changesObject (readonly)

Returns the value of attribute changes.



10
11
12
# File 'lib/typed/hash.rb', line 10

def changes
  @changes
end

#eventsObject (readonly)

Returns the value of attribute events.



11
12
13
# File 'lib/typed/hash.rb', line 11

def events
  @events
end

Instance Method Details

#[](key) ⇒ Object

Accessor



47
48
49
50
51
52
53
54
55
56
# File 'lib/typed/hash.rb', line 47

def [](key)
  if exist?(key)
    val = load(key)
    @events.fire(:read, key.to_s, val)
    return val
  else
    from = caller.is_a?(Array) ? caller.first : self.class
    raise NotDefined, "'#{key}' is not initialized\n#{from}"
  end
end

#[]=(key, val) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/typed/hash.rb', line 64

def []=(key, val)
  declare = @schema.declare_method(val)
  case declare
  when Schema::LazyValue
    # not schema
    update(key, val)
  when Schema::Ambiguous
    # TODO: How to treat these classes
    update(key, val)
    check(key)
  when Schema::Explicit
    @schema.declare!(key, declare)
    check(key) if exist?(key)
  when Schema::Implicit
    @schema.declare!(key, declare)
    update(key, val)
    check(key)
  else
    raise NotImplementedError, "[BUG] no assignment logic for: #{declare.class}"
  end
end

#check(key, type = nil) ⇒ Object



97
98
99
100
# File 'lib/typed/hash.rb', line 97

def check(key, type = nil)
  type ||= @schema[key]
  @schema.validate!(key, @hash[key.to_s], type)
end

#default(key = nil, &block) ⇒ Object

Default values



25
26
27
28
29
30
31
# File 'lib/typed/hash.rb', line 25

def default(key = nil, &block)
  if key
    @default.register_lazy(key, block)
  else
    @default
  end
end

#each(&block) ⇒ Object



112
113
114
115
116
117
# File 'lib/typed/hash.rb', line 112

def each(&block)
  keys.each do |key|
    val = self[key]
    block.call([key,val])
  end
end

#each_key(&block) ⇒ Object



119
120
121
# File 'lib/typed/hash.rb', line 119

def each_key(&block)
  keys.each(&block)
end

#each_pair(&block) ⇒ Object

Hash compat



105
106
107
108
109
110
# File 'lib/typed/hash.rb', line 105

def each_pair(&block)
  keys.each do |key|
    val = self[key]
    block.call(key,val)
  end
end

#each_value(&block) ⇒ Object



123
124
125
# File 'lib/typed/hash.rb', line 123

def each_value(&block)
  each_pair{|k,v| block.call(v)}
end

#exist?(key) ⇒ Boolean

Testing

Returns:



89
90
91
# File 'lib/typed/hash.rb', line 89

def exist?(key)
  @hash.has_key?(key.to_s)
end

#inspectObject

Utils



157
158
159
160
# File 'lib/typed/hash.rb', line 157

def inspect
  keys = @hash.keys.sort.join(',')
  "{#{keys}}"
end

#merge!(hash) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/typed/hash.rb', line 131

def merge!(hash)
  hash.each_pair do |key, val|
    self[key] = val
  end

  return self
end

#path(key) ⇒ Object

Conversions



142
143
144
# File 'lib/typed/hash.rb', line 142

def path(key)
  self[key].must.coerced(Pathname, String=>proc{|i| Pathname(i)})
end

#schema(key = nil) ⇒ Object

Schema values



36
37
38
39
40
41
42
# File 'lib/typed/hash.rb', line 36

def schema(key = nil)
  if key
    @schema[key]
  else
    @schema
  end
end

#set?(key) ⇒ Boolean

Returns:



93
94
95
# File 'lib/typed/hash.rb', line 93

def set?(key)
  !! (exist?(key) && self[key])
end

#time(key) ⇒ Object



146
147
148
# File 'lib/typed/hash.rb', line 146

def time(key)
  self[key].must.coerced(Time, Fixnum=>proc{|i| Time.at(i)})
end

#update(key, val) ⇒ Object



58
59
60
61
62
# File 'lib/typed/hash.rb', line 58

def update(key, val)
  @hash[key.to_s] = val
  @events.fire(:write, key.to_s, val)
  @changes.touch(key)
end

#utc(key) ⇒ Object



150
151
152
# File 'lib/typed/hash.rb', line 150

def utc(key)
  Time.at(self[key].to_i).utc
end

#valuesObject



127
128
129
# File 'lib/typed/hash.rb', line 127

def values
  keys.map{|key| self[key]}
end