Class: LeapCli::Config::Object
- Defined in:
- lib/leap_cli/config/object.rb
Overview
This class represents the configuration for a single node, service, or tag. Also, all the nested hashes are also of this type.
It is called ‘object’ because it corresponds to an Object in JSON.
Instance Attribute Summary collapse
-
#node ⇒ Object
readonly
Returns the value of attribute node.
Instance Method Summary collapse
-
#[](key) ⇒ Object
FETCHING VALUES.
-
#deep_merge!(object, prefer_self = false) ⇒ Object
A deep (recursive) merge with another Config::Object.
-
#default ⇒ Object
override behavior of #default() from Hash.
-
#dump_json ⇒ Object
export JSON.
-
#dump_yaml ⇒ Object
export YAML.
- #environment ⇒ Object
- #environment=(e) ⇒ Object
- #eval_file(filename) ⇒ Object
- #evaluate(context = @node) ⇒ Object
- #get(key) ⇒ Object
-
#get!(key) ⇒ Object
Like a normal Hash#[], except:.
-
#hkey ⇒ Object
Overrride some default methods in Hash that are likely to be used as attributes.
-
#inherit_from!(object) ⇒ Object
like a reverse deep merge (self takes precedence).
-
#initialize(manager = nil, node = nil) ⇒ Object
constructor
A new instance of Object.
- #key ⇒ Object
- #manager ⇒ Object (also: #global)
-
#method_missing(method, *args, &block) ⇒ Object
make hash addressable like an object (e.g. obj available as obj.name).
-
#pick(*keys) ⇒ Object
Make a copy of ourselves, except only including the specified keys.
Methods inherited from Hash
Constructor Details
#initialize(manager = nil, node = nil) ⇒ Object
Returns a new instance of Object.
51 52 53 54 55 56 57 58 |
# File 'lib/leap_cli/config/object.rb', line 51 def initialize(manager=nil, node=nil) # keep a global pointer around to the config manager. used a lot in the eval strings and templates # (which are evaluated in the context of Config::Object) @manager = manager # an object that is a node as @node equal to self, otherwise all the child objects point back to the top level node. @node = node || self end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
Instance Attribute Details
#node ⇒ Object (readonly)
Returns the value of attribute node.
49 50 51 |
# File 'lib/leap_cli/config/object.rb', line 49 def node @node end |
Instance Method Details
#[](key) ⇒ Object
FETCHING VALUES
102 103 104 |
# File 'lib/leap_cli/config/object.rb', line 102 def [](key) get(key) end |
#deep_merge!(object, prefer_self = false) ⇒ Object
A deep (recursive) merge with another Config::Object.
If prefer_self is set to true, the value from self will be picked when there is a conflict that cannot be merged.
Merging rules:
-
If a value is a hash, we recursively merge it.
-
If the value is simple, like a string, the new one overwrites the value.
-
If the value is an array:
-
If both old and new values are arrays, the new one replaces the old.
-
If one of the values is simple but the other is an array, the simple is added to the array.
-
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 |
# File 'lib/leap_cli/config/object.rb', line 175 def deep_merge!(object, prefer_self=false) object.each do |key,new_value| if self.has_key?('+'+key) mode = :add old_value = self.fetch '+'+key, nil self.delete('+'+key) elsif self.has_key?('-'+key) mode = :subtract old_value = self.fetch '-'+key, nil self.delete('-'+key) else mode = :normal old_value = self.fetch key, nil end # clean up boolean new_value = true if new_value == "true" new_value = false if new_value == "false" old_value = true if old_value == "true" old_value = false if old_value == "false" # merge hashes if old_value.is_a?(Hash) || new_value.is_a?(Hash) value = Config::Object.new(@manager, @node) old_value.is_a?(Hash) ? value.deep_merge!(old_value) : (value[key] = old_value if !old_value.nil?) new_value.is_a?(Hash) ? value.deep_merge!(new_value, prefer_self) : (value[key] = new_value if !new_value.nil?) # merge nil elsif new_value.nil? value = old_value elsif old_value.nil? value = new_value # merge arrays when one value is not an array elsif old_value.is_a?(Array) && !new_value.is_a?(Array) (value = (old_value.dup << new_value).compact.uniq).delete('REQUIRED') elsif new_value.is_a?(Array) && !old_value.is_a?(Array) (value = (new_value.dup << old_value).compact.uniq).delete('REQUIRED') # merge two arrays elsif old_value.is_a?(Array) && new_value.is_a?(Array) if mode == :add value = (old_value + new_value).sort.uniq elsif mode == :subtract value = new_value - old_value elsif prefer_self value = old_value else value = new_value end # catch errors elsif type_mismatch?(old_value, new_value) raise 'Type mismatch. Cannot merge %s (%s) with %s (%s). Key is "%s", name is "%s".' % [ old_value.inspect, old_value.class, new_value.inspect, new_value.class, key, self.class ] # merge simple strings & numbers else if prefer_self value = old_value else value = new_value end end # save value self[key] = value end self end |
#default ⇒ Object
override behavior of #default() from Hash
127 128 129 |
# File 'lib/leap_cli/config/object.rb', line 127 def default get!('default') end |
#dump_json ⇒ Object
export JSON
88 89 90 91 |
# File 'lib/leap_cli/config/object.rb', line 88 def dump_json evaluate(@node) JSON.sorted_generate(self) end |
#dump_yaml ⇒ Object
export YAML
We use pure ruby yaml exporter ya2yaml instead of SYCK or PSYCH because it allows us greater compatibility regardless of installed ruby version and greater control over how the yaml is exported (sorted keys, in particular).
80 81 82 83 |
# File 'lib/leap_cli/config/object.rb', line 80 def dump_yaml evaluate(@node) sorted_ya2yaml(:syck_compatible => true) end |
#environment ⇒ Object
69 70 71 |
# File 'lib/leap_cli/config/object.rb', line 69 def environment self['environment'] end |
#environment=(e) ⇒ Object
65 66 67 |
# File 'lib/leap_cli/config/object.rb', line 65 def environment=(e) self.store('environment', e) end |
#eval_file(filename) ⇒ Object
272 273 274 |
# File 'lib/leap_cli/config/object.rb', line 272 def eval_file(filename) evaluate_ruby(filename, File.read(filename)) end |
#evaluate(context = @node) ⇒ Object
93 94 95 96 |
# File 'lib/leap_cli/config/object.rb', line 93 def evaluate(context=@node) evaluate_everything(context) late_evaluate_everything(context) end |
#get(key) ⇒ Object
118 119 120 121 122 123 124 |
# File 'lib/leap_cli/config/object.rb', line 118 def get(key) begin get!(key) rescue NoMethodError nil end end |
#get!(key) ⇒ Object
Like a normal Hash#[], except:
(1) lazily eval dynamic values when we encounter them. (i.e. strings that start with “= ”)
(2) support for nested references in a single string (e.g. [‘a.b’] is the same as [‘a’])
the dot path is always absolute, starting at the top-most object.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/leap_cli/config/object.rb', line 139 def get!(key) key = key.to_s if self.has_key?(key) fetch_value(key) elsif key =~ /\./ # for keys with with '.' in them, we start from the root object (@node). keys = key.split('.') value = @node.get!(keys.first) if value.is_a? Config::Object value.get!(keys[1..-1].join('.')) else value end else raise NoMethodError.new(key, "No method '#{key}' for #{self.class}") end end |
#hkey ⇒ Object
Overrride some default methods in Hash that are likely to be used as attributes.
108 |
# File 'lib/leap_cli/config/object.rb', line 108 alias_method :hkey, :key |
#inherit_from!(object) ⇒ Object
like a reverse deep merge (self takes precedence)
253 254 255 |
# File 'lib/leap_cli/config/object.rb', line 253 def inherit_from!(object) self.deep_merge!(object, true) end |
#key ⇒ Object
109 |
# File 'lib/leap_cli/config/object.rb', line 109 def key; get('key'); end |
#manager ⇒ Object Also known as: global
60 61 62 |
# File 'lib/leap_cli/config/object.rb', line 60 def manager ManagerBinding.new(@manager, self) end |
#pick(*keys) ⇒ Object
Make a copy of ourselves, except only including the specified keys.
Also, the result is flattened to a single hash, so a key of ‘a.b’ becomes ‘a_b’
262 263 264 265 266 267 268 269 270 |
# File 'lib/leap_cli/config/object.rb', line 262 def pick(*keys) keys.map(&:to_s).inject(self.class.new(@manager)) do |hsh, key| value = self.get(key) if !value.nil? hsh[key.gsub('.','_')] = value end hsh end end |