lib/map.rb in map-4.2.0 vs lib/map.rb in map-4.3.0
- old
+ new
@@ -1,7 +1,7 @@
class Map < Hash
- Version = '4.2.0' unless defined?(Version)
+ Version = '4.3.0' unless defined?(Version)
Load = Kernel.method(:load) unless defined?(Load)
class << Map
def version
Map::Version
@@ -182,10 +182,12 @@
super(&block)
when 1
first = args.first
case first
+ when nil, false
+ nil
when Hash
initialize_from_hash(first)
when Array
initialize_from_array(first)
else
@@ -225,13 +227,20 @@
end
def map_for(hash)
klass.map_for(hash)
end
+=begin
def self.convert_key(key)
key.kind_of?(Symbol) ? key.to_s : key
end
+=end
+
+ def self.convert_key(key)
+ key = key.kind_of?(Symbol) ? key.to_s : key
+ end
+
def convert_key(key)
if klass.respond_to?(:convert_key)
klass.convert_key(key)
else
Map.convert_key(key)
@@ -310,15 +319,17 @@
__set__(key, val)
end
alias_method 'store', '[]='
def [](key)
- __get__(convert_key(key))
+ key = convert_key(key)
+ __get__(key)
end
def fetch(key, *args, &block)
- super(convert_key(key), *args, &block)
+ key = convert_key(key)
+ super(key, *args, &block)
end
def key?(key)
super(convert_key(key))
end
@@ -551,25 +562,17 @@
hash[key] = val
end
hash
end
- def as_hash
- @class = Hash
- yield
- ensure
- @class = nil
+ def to_yaml( opts = {} )
+ map = self
+ YAML.quick_emit(self.object_id, opts){|out|
+ out.map('!omap'){|m| map.each{|k,v| m.add(k, v)}}
+ }
end
- def class
- @class || super
- end
-
- def to_yaml(*args, &block)
- as_hash{ super }
- end
-
def to_array
array = []
each{|*pair| array.push(pair)}
array
end
@@ -623,24 +626,36 @@
end
# support for compound key indexing and depth first iteration
#
def get(*keys)
- keys = keys.flatten
- return self[keys.first] if keys.size <= 1
+ keys = key_for(keys)
+ if keys.size <= 1
+ if !self.has_key?(keys.first) && block_given?
+ return yield
+ else
+ return self[keys.first]
+ end
+ end
keys, key = keys[0..-2], keys[-1]
collection = self
keys.each do |k|
k = alphanumeric_key_for(k)
collection = collection[k]
return collection unless collection.respond_to?('[]')
end
- collection[alphanumeric_key_for(key)]
+ alphanumeric_key = alphanumeric_key_for(key)
+
+ if !collection_has_key?(collection, alphanumeric_key) && block_given?
+ yield
+ else
+ collection[alphanumeric_key]
+ end
end
def has?(*keys)
- keys = keys.flatten
+ keys = key_for(keys)
collection = self
return collection_has_key?(collection, keys.first) if keys.size <= 1
keys, key = keys[0..-2], keys[-1]
keys.each do |k|
k = alphanumeric_key_for(k)
@@ -693,10 +708,13 @@
spec.each do |keys, value|
keys = Array(keys).flatten
collection = self
+
+ keys = key_for(keys)
+
if keys.size <= 1
key = keys.first
collection[key] = value
next
end
@@ -785,9 +803,54 @@
key.to_s =~ %r/^\d+$/ ? Integer(key) : key
end
def alphanumeric_key_for(key)
Map.alphanumeric_key_for(key)
+ end
+
+## key path support
+#
+ def self.dot_key_for(*keys)
+ dot = keys.compact.flatten.join('.')
+ dot.split(%r/\s*[,.:_-]\s*/).map{|part| part =~ %r/^\d+$/ ? Integer(part) : part}
+ end
+
+ def self.dot_keys
+ @@dot_keys = {} unless defined?(@@dot_keys)
+ @@dot_keys
+ end
+
+ def self.dot_keys?
+ ancestors.each do |ancestor|
+ return dot_keys[ancestor] if dot_keys.has_key?(ancestor)
+ end
+ false
+ end
+
+ def dot_keys?
+ @dot_keys = false unless defined?(@dot_keys)
+ @dot_keys
+ end
+
+ def self.dot_keys!(boolean = true)
+ dot_keys[self] = !!boolean
+ end
+
+ def dot_keys!(boolean = true)
+ @dot_keys = !!boolean
+ end
+
+ def self.key_for(*keys)
+ return keys.flatten unless dot_keys?
+ self.dot_key_for(*keys)
+ end
+
+ def key_for(*keys)
+ if dot_keys?
+ self.class.dot_key_for(*keys)
+ else
+ self.class.key_for(*keys)
+ end
end
## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
#
def Map.depth_first_each(enumerable, path = [], accum = [], &block)