Class: Burke::Holder

Inherits:
Hash show all
Defined in:
lib/burke/holder.rb

Defined Under Namespace

Classes: CircularReadError

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, &block) ⇒ Holder

Returns a new instance of Holder.



60
61
62
63
64
65
66
67
68
69
# File 'lib/burke/holder.rb', line 60

def initialize *args, &block
  if block_given?
    self.instance_exec self, &block
  else
    super
  end
  
  @currently_getting = []
  @currently_getting_mutex = Mutex.new
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/burke/holder.rb', line 134

def method_missing name, *args, &block
  base, ending = *String(name).match(/(\w*)([!?=]?)/).to_a[1..-1]
  key = normalize_key(base)
  case ending
  when '?'
    if field_exists? key
      !!self[key]
    else
      super
    end
  when '='
    if field_exists? key
      self[key] = args[0]
    else
      super
    end
  when ''
    if field_exists? key
      if args.empty?
        v = self[key]
        if block_given?
          if v.respond_to? 'holder_instance_exec?' and v.holder_instance_exec?
            v.instance_exec v, &block
          else
            yield v
          end
        end
        v
      else
        self[key] = args[0]
      end
    else
      super
    end
  else
    super
  end
end

Class Attribute Details

.defaultsObject

Returns the value of attribute defaults.



31
32
33
# File 'lib/burke/holder.rb', line 31

def defaults
  @defaults
end

Class Method Details

.[](hash) ⇒ Object



55
56
57
# File 'lib/burke/holder.rb', line 55

def [](hash)
  new.merge hash
end

.field(name, &block) ⇒ Object



40
41
42
43
44
45
# File 'lib/burke/holder.rb', line 40

def field name, &block
  name = String(name)
  @fields << name
  @fields.uniq!
  @defaults[name] = block if block_given?
end

.field_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/burke/holder.rb', line 51

def field_exists? name
  @fields.include? name
end

.fields(*names) ⇒ Object



47
48
49
# File 'lib/burke/holder.rb', line 47

def fields *names
  names.each { |name| field name }
end

.inherited(clazz) ⇒ Object



33
34
35
36
37
38
# File 'lib/burke/holder.rb', line 33

def inherited clazz
  clazz.instance_eval do
    @fields = []
    @defaults = {}
  end
end

Instance Method Details

#[](key) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/burke/holder.rb', line 79

def [](key)
  key = normalize_key key
  assert_field_exists! key
  id = "#{key}-#{Thread.current.object_id}"
  @currently_getting_mutex.synchronize do
    if @currently_getting.include? id
      raise CircularReadError.new "circular read for field '#{key}'" 
    end
    @currently_getting << id
  end
  val = if key? key
    super
  elsif self.class.defaults.key? key
    self.instance_eval(&self.class.defaults[key])
  else
    nil
  end
  @currently_getting_mutex.synchronize do
    @currently_getting.delete id
  end
  val
end

#[]=(key, value) ⇒ Object



102
103
104
105
106
# File 'lib/burke/holder.rb', line 102

def []=(key, value)
  key = normalize_key key
  assert_field_exists! key
  super
end

#assert_field_exists!(name) ⇒ Object



181
182
183
184
185
# File 'lib/burke/holder.rb', line 181

def assert_field_exists! name
  unless field_exists? name
    raise NoMethodError, "field '#{name}' is not defined for this Holder."
  end
end

#delete(key) ⇒ Object



130
131
132
# File 'lib/burke/holder.rb', line 130

def delete key
  super normalize_key(key)
end

#field_exists?(name) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/burke/holder.rb', line 177

def field_exists? name
  self.class.field_exists? name
end

#holder_instance_exec?Boolean

Returns:

  • (Boolean)


28
# File 'lib/burke/holder.rb', line 28

def holder_instance_exec? ; true ; end

#merge(other) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/burke/holder.rb', line 116

def merge other
  holder = self.class.new
  
  self.each do |k, v|
    holder[k] = v
  end
  
  other.each do |k, v|
    holder[k] ||= v
  end
  
  holder
end

#merge!(other) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/burke/holder.rb', line 108

def merge! other
  other.each do |k, v|
    self[k] ||= v
  end
  
  nil
end

#normalize_key(key) ⇒ Object



173
174
175
# File 'lib/burke/holder.rb', line 173

def normalize_key key
  String(key)
end

#to_hashObject



71
72
73
74
75
76
77
# File 'lib/burke/holder.rb', line 71

def to_hash
  out = {}
  keys.concat(self.class.defaults.keys).uniq.each do |k|
    out[k] = Holder === self[k] ? self[k].to_hash : self[k]
  end
  out
end