map 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -0
- data/README +4 -0
- data/Rakefile +4 -2
- data/a.rb +7 -0
- data/lib/map.rb +83 -20
- data/map.gemspec +4 -2
- data/test/lib/testing.rb +1 -1
- data/test/map_test.rb +34 -0
- metadata +6 -4
data/LICENSE
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
same as ruby's
|
data/README
CHANGED
data/Rakefile
CHANGED
@@ -3,6 +3,9 @@ This.author = "Ara T. Howard"
|
|
3
3
|
This.email = "ara.t.howard@gmail.com"
|
4
4
|
This.homepage = "https://github.com/ahoward/#{ This.lib }"
|
5
5
|
|
6
|
+
task :license do
|
7
|
+
open('LICENSE', 'w'){|fd| fd.puts "same as ruby's"}
|
8
|
+
end
|
6
9
|
|
7
10
|
task :default do
|
8
11
|
puts((Rake::Task.tasks.map{|task| task.name.gsub(/::/,':')} - ['default']).sort)
|
@@ -26,11 +29,10 @@ def run_tests!(which = nil)
|
|
26
29
|
|
27
30
|
div = ('=' * 119)
|
28
31
|
line = ('-' * 119)
|
29
|
-
helper = "-r ./test/helper.rb" if test(?e, "./test/helper.rb")
|
30
32
|
|
31
33
|
test_rbs.each_with_index do |test_rb, index|
|
32
34
|
testno = index + 1
|
33
|
-
command = "#{ This.ruby } -I ./lib -I ./test/lib #{
|
35
|
+
command = "#{ This.ruby } -I ./lib -I ./test/lib #{ test_rb }"
|
34
36
|
|
35
37
|
puts
|
36
38
|
say(div, :color => :cyan, :bold => true)
|
data/a.rb
ADDED
data/lib/map.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Map < Hash
|
2
|
-
Version = '4.
|
2
|
+
Version = '4.3.0' unless defined?(Version)
|
3
3
|
Load = Kernel.method(:load) unless defined?(Load)
|
4
4
|
|
5
5
|
class << Map
|
@@ -184,6 +184,8 @@ class Map < Hash
|
|
184
184
|
when 1
|
185
185
|
first = args.first
|
186
186
|
case first
|
187
|
+
when nil, false
|
188
|
+
nil
|
187
189
|
when Hash
|
188
190
|
initialize_from_hash(first)
|
189
191
|
when Array
|
@@ -227,9 +229,16 @@ class Map < Hash
|
|
227
229
|
klass.map_for(hash)
|
228
230
|
end
|
229
231
|
|
232
|
+
=begin
|
230
233
|
def self.convert_key(key)
|
231
234
|
key.kind_of?(Symbol) ? key.to_s : key
|
232
235
|
end
|
236
|
+
=end
|
237
|
+
|
238
|
+
def self.convert_key(key)
|
239
|
+
key = key.kind_of?(Symbol) ? key.to_s : key
|
240
|
+
end
|
241
|
+
|
233
242
|
def convert_key(key)
|
234
243
|
if klass.respond_to?(:convert_key)
|
235
244
|
klass.convert_key(key)
|
@@ -312,11 +321,13 @@ class Map < Hash
|
|
312
321
|
alias_method 'store', '[]='
|
313
322
|
|
314
323
|
def [](key)
|
315
|
-
|
324
|
+
key = convert_key(key)
|
325
|
+
__get__(key)
|
316
326
|
end
|
317
327
|
|
318
328
|
def fetch(key, *args, &block)
|
319
|
-
|
329
|
+
key = convert_key(key)
|
330
|
+
super(key, *args, &block)
|
320
331
|
end
|
321
332
|
|
322
333
|
def key?(key)
|
@@ -553,19 +564,11 @@ class Map < Hash
|
|
553
564
|
hash
|
554
565
|
end
|
555
566
|
|
556
|
-
def
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
end
|
562
|
-
|
563
|
-
def class
|
564
|
-
@class || super
|
565
|
-
end
|
566
|
-
|
567
|
-
def to_yaml(*args, &block)
|
568
|
-
as_hash{ super }
|
567
|
+
def to_yaml( opts = {} )
|
568
|
+
map = self
|
569
|
+
YAML.quick_emit(self.object_id, opts){|out|
|
570
|
+
out.map('!omap'){|m| map.each{|k,v| m.add(k, v)}}
|
571
|
+
}
|
569
572
|
end
|
570
573
|
|
571
574
|
def to_array
|
@@ -625,8 +628,14 @@ class Map < Hash
|
|
625
628
|
# support for compound key indexing and depth first iteration
|
626
629
|
#
|
627
630
|
def get(*keys)
|
628
|
-
keys = keys
|
629
|
-
|
631
|
+
keys = key_for(keys)
|
632
|
+
if keys.size <= 1
|
633
|
+
if !self.has_key?(keys.first) && block_given?
|
634
|
+
return yield
|
635
|
+
else
|
636
|
+
return self[keys.first]
|
637
|
+
end
|
638
|
+
end
|
630
639
|
keys, key = keys[0..-2], keys[-1]
|
631
640
|
collection = self
|
632
641
|
keys.each do |k|
|
@@ -634,11 +643,17 @@ class Map < Hash
|
|
634
643
|
collection = collection[k]
|
635
644
|
return collection unless collection.respond_to?('[]')
|
636
645
|
end
|
637
|
-
|
646
|
+
alphanumeric_key = alphanumeric_key_for(key)
|
647
|
+
|
648
|
+
if !collection_has_key?(collection, alphanumeric_key) && block_given?
|
649
|
+
yield
|
650
|
+
else
|
651
|
+
collection[alphanumeric_key]
|
652
|
+
end
|
638
653
|
end
|
639
654
|
|
640
655
|
def has?(*keys)
|
641
|
-
keys = keys
|
656
|
+
keys = key_for(keys)
|
642
657
|
collection = self
|
643
658
|
return collection_has_key?(collection, keys.first) if keys.size <= 1
|
644
659
|
keys, key = keys[0..-2], keys[-1]
|
@@ -695,6 +710,9 @@ class Map < Hash
|
|
695
710
|
keys = Array(keys).flatten
|
696
711
|
|
697
712
|
collection = self
|
713
|
+
|
714
|
+
keys = key_for(keys)
|
715
|
+
|
698
716
|
if keys.size <= 1
|
699
717
|
key = keys.first
|
700
718
|
collection[key] = value
|
@@ -789,6 +807,51 @@ class Map < Hash
|
|
789
807
|
Map.alphanumeric_key_for(key)
|
790
808
|
end
|
791
809
|
|
810
|
+
## key path support
|
811
|
+
#
|
812
|
+
def self.dot_key_for(*keys)
|
813
|
+
dot = keys.compact.flatten.join('.')
|
814
|
+
dot.split(%r/\s*[,.:_-]\s*/).map{|part| part =~ %r/^\d+$/ ? Integer(part) : part}
|
815
|
+
end
|
816
|
+
|
817
|
+
def self.dot_keys
|
818
|
+
@@dot_keys = {} unless defined?(@@dot_keys)
|
819
|
+
@@dot_keys
|
820
|
+
end
|
821
|
+
|
822
|
+
def self.dot_keys?
|
823
|
+
ancestors.each do |ancestor|
|
824
|
+
return dot_keys[ancestor] if dot_keys.has_key?(ancestor)
|
825
|
+
end
|
826
|
+
false
|
827
|
+
end
|
828
|
+
|
829
|
+
def dot_keys?
|
830
|
+
@dot_keys = false unless defined?(@dot_keys)
|
831
|
+
@dot_keys
|
832
|
+
end
|
833
|
+
|
834
|
+
def self.dot_keys!(boolean = true)
|
835
|
+
dot_keys[self] = !!boolean
|
836
|
+
end
|
837
|
+
|
838
|
+
def dot_keys!(boolean = true)
|
839
|
+
@dot_keys = !!boolean
|
840
|
+
end
|
841
|
+
|
842
|
+
def self.key_for(*keys)
|
843
|
+
return keys.flatten unless dot_keys?
|
844
|
+
self.dot_key_for(*keys)
|
845
|
+
end
|
846
|
+
|
847
|
+
def key_for(*keys)
|
848
|
+
if dot_keys?
|
849
|
+
self.class.dot_key_for(*keys)
|
850
|
+
else
|
851
|
+
self.class.key_for(*keys)
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
792
855
|
## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
|
793
856
|
#
|
794
857
|
def Map.depth_first_each(enumerable, path = [], accum = [], &block)
|
data/map.gemspec
CHANGED
@@ -3,15 +3,17 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "map"
|
6
|
-
spec.version = "4.
|
6
|
+
spec.version = "4.3.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "map"
|
9
9
|
spec.description = "description: map kicks the ass"
|
10
10
|
|
11
11
|
spec.files =
|
12
|
-
["
|
12
|
+
["LICENSE",
|
13
|
+
"README",
|
13
14
|
"Rakefile",
|
14
15
|
"TODO",
|
16
|
+
"a.rb",
|
15
17
|
"lib",
|
16
18
|
"lib/map",
|
17
19
|
"lib/map.rb",
|
data/test/lib/testing.rb
CHANGED
data/test/map_test.rb
CHANGED
@@ -24,6 +24,11 @@ Testing Map do
|
|
24
24
|
assert{ Map.new(*array) }
|
25
25
|
end
|
26
26
|
|
27
|
+
testing 'that the constructor does not die when passed nil or false' do
|
28
|
+
assert{ Map.new(nil) }
|
29
|
+
assert{ Map.new(false) }
|
30
|
+
end
|
31
|
+
|
27
32
|
testing 'that the contructor accepts an even sized array' do
|
28
33
|
arrays = [
|
29
34
|
[ %w( k v ), %w( key val ) ],
|
@@ -327,6 +332,35 @@ Testing Map do
|
|
327
332
|
assert{ m[:x][:y][:z] == 42.0 }
|
328
333
|
end
|
329
334
|
|
335
|
+
testing 'that maps can support compound key/val setting via key.dot notation' do
|
336
|
+
m = Class.new(Map){ dot_keys! }.new
|
337
|
+
assert{ m.set('a.b.c', 42) }
|
338
|
+
assert{ m[:a][:b][:c] == 42 }
|
339
|
+
assert{ m.get('a.b.c') == 42 }
|
340
|
+
assert{ m.set('x.y.z' => 42.0, 'A.2' => 'forty-two') }
|
341
|
+
assert{ m[:A].is_a?(Array) }
|
342
|
+
assert{ m[:A].size == 3}
|
343
|
+
assert{ m[:A][2] == 'forty-two' }
|
344
|
+
assert{ m[:x][:y].is_a?(Hash) }
|
345
|
+
assert{ m[:x][:y][:z] == 42.0 }
|
346
|
+
assert{ m.has?('a.b.c') }
|
347
|
+
assert{ m.has?('x.y.z') }
|
348
|
+
assert{ m.has?('A.2') }
|
349
|
+
end
|
350
|
+
|
351
|
+
testing 'that Map#get supports providing a default value in a block' do
|
352
|
+
m = Map.new
|
353
|
+
m.set(:a, :b, :c, 42)
|
354
|
+
m.set(:z, 1)
|
355
|
+
|
356
|
+
assert { m.get(:x) {1} == 1 }
|
357
|
+
assert { m.get(:z) {2} == 1 }
|
358
|
+
assert { m.get(:a, :b, :d) {1} == 1 }
|
359
|
+
assert { m.get(:a, :b, :c) {1} == 42 }
|
360
|
+
assert { m.get(:a, :b) {1} == Map.new({:c => 42}) }
|
361
|
+
assert { m.get(:a, :aa) {1} == 1 }
|
362
|
+
end
|
363
|
+
|
330
364
|
testing 'that setting a sub-container does not eff up the container values' do
|
331
365
|
m = Map.new
|
332
366
|
assert{ m.set(:array => [0,1,2]) }
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: map
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 51
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 4
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 4.
|
10
|
+
version: 4.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ara T. Howard
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-08-17 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -28,9 +28,11 @@ extensions: []
|
|
28
28
|
extra_rdoc_files: []
|
29
29
|
|
30
30
|
files:
|
31
|
+
- LICENSE
|
31
32
|
- README
|
32
33
|
- Rakefile
|
33
34
|
- TODO
|
35
|
+
- a.rb
|
34
36
|
- lib/map.rb
|
35
37
|
- lib/map/options.rb
|
36
38
|
- lib/map/struct.rb
|