Class: ActiveConfig::HashConfig

Inherits:
Hash
  • Object
show all
Defined in:
lib/active_config/hash_config.rb

Direct Known Subclasses

HashWithHooks

Constant Summary collapse

@@no_key =

Allow hash.default => hash without breaking Hash’s usage of default(key)

[ :no_key ]

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Hash

#weave, #weave!

Constructor Details

#initialize(constructor = {}) ⇒ HashConfig

Returns a new instance of HashConfig.



4
5
6
7
# File 'lib/active_config/hash_config.rb', line 4

def initialize(constructor = {})
  super()
  update(constructor)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

dotted notation can now be used with arguments (useful for creating mock objects) in the YAML file the method name is a key (just like usual), argument(s) form a nested key, and the value will get returned.

For example loading to variable foo a yaml file that looks like: customer:

id: 12345678
verified:
  phone: verified
  :address: info_not_available
  ? [name, employer]
  : not_verified

Allows the following calls: foo.customer.id –> 12345678 foo.customer.verified.phone –> verified foo.customer.verified(“phone”) –> verified foo.customer.verified(“name”, “employer”) –> not_verified foo.customer.verified(:address) –> info_not_available

Note that :address is specified as a symbol, where phone is just a string. Depending on what kind of parameter the method being mocked out is going to be called with, define in the YAML file either a string or a symbol.

This also works inside the composite array keys.



174
175
176
177
178
179
180
# File 'lib/active_config/hash_config.rb', line 174

def method_missing(method, *args)
  method = method.to_s
  if args.size==1 and method.to_s=~/=$/
    return  self[method.to_s.sub(/=$/,'')]=args[0]
  end
  args.inject(self[method]){|s,e|s and s[e]}
end

Class Method Details

._make_indifferent(x, opts = {}) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/active_config/hash_config.rb', line 127

def self._make_indifferent(x,opts={})
  return x if  opts[:freeze] and x.frozen?
  case x
  when HashConfig
      x.each_pair do | k, v |
        x[k.freeze] = _make_indifferent(v,opts)
      end
  when Hash
    x = HashConfig.new.merge(x)
    x.each_pair do | k, v |
      x[k.freeze] = _make_indifferent(v,opts)
    end
    # STDERR.puts "x = #{x.inspect}:#{x.class}"
  when Array
    x.collect!  do | v |
      _make_indifferent(v,opts)
    end
  end

  x.freeze if opts[:freeze]
  x
end

._make_indifferent_and_freeze(x) ⇒ Object



104
105
106
# File 'lib/active_config/hash_config.rb', line 104

def self._make_indifferent_and_freeze(x)
  _make_indifferent(x,:freeze => true)
end

.recursive_freeze(x) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/active_config/hash_config.rb', line 115

def self.recursive_freeze x
  return x if x.frozen?
  case x
  when HashConfig,Hash
      x.each_pair do | k, v |
        x[recursive_freeze(k)] = recursive_freeze(v) 
      end
  when Array
    x.collect! {|v|freeze(v)}
  end
  x.freeze 
end

Instance Method Details

#[](key) ⇒ Object

Why the &*#^@*^&$ isn’t HashWithIndifferentAccess actually doing this?



185
186
187
188
# File 'lib/active_config/hash_config.rb', line 185

def [](key)
  key = key.to_s if key.kind_of?(Symbol)
  super(key)
end

#[]=(key, value) ⇒ Object

Assigns a new value to the hash:

hash = HashWithIndifferentAccess.new
hash[:key] = "value"


24
25
26
# File 'lib/active_config/hash_config.rb', line 24

def []=(key, value)
  regular_writer(convert_key(key), convert_value(value))
end

#default(key = @@no_key) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/active_config/hash_config.rb', line 8

def default(key = nil)
  if key.is_a?(Symbol) && include?(key = key.to_s)
    self[key]
  else
    super
  end
end

#delete(key) ⇒ Object

Removes a specified key from the hash.



88
89
90
# File 'lib/active_config/hash_config.rb', line 88

def delete(key)
  super(convert_key(key))
end

#dupObject

HashWithIndifferentAccess#dup always returns HashWithIndifferentAccess! – kurt 2007/10/18



77
78
79
# File 'lib/active_config/hash_config.rb', line 77

def dup
  self.class.new(self)
end

#fetch(key, *extras) ⇒ Object

Fetches the value for the specified key, same as doing hash



61
62
63
# File 'lib/active_config/hash_config.rb', line 61

def fetch(key, *extras)
  super(convert_key(key), *extras)
end

#freeze!Object



107
108
109
110
111
112
113
114
# File 'lib/active_config/hash_config.rb', line 107

def freeze!
  return false if self.frozen?
  self.each_pair do | k, v |
    self[self.class.recursive_freeze(k)] = self.class.recursive_freeze(v) 
  end
  self.freeze
  self 
end

#key?(key) ⇒ Boolean Also known as: include?, has_key?, member?

Checks the hash for a key matching the argument passed in:

hash = HashWithIndifferentAccess.new
hash["key"] = "value"
hash.key? :key  # => true
hash.key? "key" # => true

Returns:

  • (Boolean)


52
53
54
# File 'lib/active_config/hash_config.rb', line 52

def key?(key)
  super(convert_key(key))
end

#merge(hash) ⇒ Object

Merges the instantized and the specified hashes together, giving precedence to the values from the second hash Does not overwrite the existing hash.



83
84
85
# File 'lib/active_config/hash_config.rb', line 83

def merge(hash)
  self.dup.update(hash)
end

#regular_updateObject



17
# File 'lib/active_config/hash_config.rb', line 17

alias_method :regular_update, :update

#regular_writerObject



16
# File 'lib/active_config/hash_config.rb', line 16

alias_method :regular_writer, :[]=

#to_hashObject

Convert to a Hash with String keys.



93
94
95
# File 'lib/active_config/hash_config.rb', line 93

def to_hash
  Hash.new(default).merge(self)
end

#update(other_hash) ⇒ Object Also known as: merge!

Updates the instantized hash with values from the second:

hash_1 = HashWithIndifferentAccess.new
hash_1[:key] = "value"

hash_2 = HashWithIndifferentAccess.new
hash_2[:key] = "New Value!"

hash_1.update(hash_2) # => {"key"=>"New Value!"}


38
39
40
41
# File 'lib/active_config/hash_config.rb', line 38

def update(other_hash)
  other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
  self
end

#values_at(*indices) ⇒ Object

Returns an array of the values at the specified indices:

hash = HashWithIndifferentAccess.new
hash[:a] = "x"
hash[:b] = "y"
hash.values_at("a", "b") # => ["x", "y"]


72
73
74
# File 'lib/active_config/hash_config.rb', line 72

def values_at(*indices)
  indices.collect {|key| self[convert_key(key)]}
end