lib/skippy/config.rb in skippy-0.2.0.a vs lib/skippy/config.rb in skippy-0.3.0.a
- old
+ new
@@ -3,38 +3,24 @@
require 'skippy/error'
class Skippy::Config < Hash
- attr_accessor :path
+ attr_reader :path
class MissingPathError < Skippy::Error; end
def self.load(path, defaults = {})
if path.exist?
json = File.read(path)
config = JSON.parse(json,
symbolize_names: true,
- object_class: self
- )
+ object_class: self)
else
- config = self.new
+ config = new
end
- # Need to merge nested defaults.
- config.merge!(defaults) { |_key, value, default|
- if value.is_a?(Hash) && default.is_a?(Hash)
- # Deep merge in order to merge nested hashes.
- # Note: This currently doesn't merge arrays.
- # http://stackoverflow.com/a/9381776/486990
- merger = proc { |_k, v1, v2|
- Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
- }
- default.merge(value, &merger)
- else
- value || default
- end
- }
+ config.merge_defaults(defaults)
config.path = path
config
end
def get(key_path, default = nil)
@@ -75,24 +61,43 @@
def update(hash)
if hash.keys.first.is_a?(String)
update_from_key_paths(hash)
else
- update_from_hash(hash)
+ deep_merge!(hash)
end
self
end
def inspect
"#{super}:#{self.class.name}"
end
+ # @param [Hash] defaults
+ def merge_defaults(defaults)
+ merge!(defaults) { |_key, value, default|
+ if value.is_a?(Hash) && default.is_a?(Hash)
+ # Deep merge in order to merge nested hashes.
+ # Note: This currently doesn't merge arrays.
+ # http://stackoverflow.com/a/9381776/486990
+ merger = proc { |_k, v1, v2|
+ v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2
+ }
+ default.merge(value, &merger)
+ else
+ # TODO(thomthom): Should `merger` include this logic?
+ value || default
+ end
+ }
+ end
+
private
- def update_from_hash(hash)
+ # @param [Hash] hash
+ def deep_merge!(hash)
merger = proc { |_key, v1, v2|
- Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
+ v1.is_a?(Hash) && v2.is_a?(Hash) ? v1.merge(v2, &merger) : v2
}
merge!(hash, &merger)
end
def update_from_key_paths(key_paths)
@@ -103,10 +108,10 @@
def key_parts(key_path)
if key_path.is_a?(Symbol)
[key_path]
else
- key_path.split('/').map { |key| key.intern }
+ key_path.split('/').map(&:intern)
end
end
def get_item(key_path)
parts = key_parts(key_path)