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)