map 1.4.0 → 1.5.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/README +39 -3
- data/lib/map.rb +2 -1
- data/lib/map/options.rb +151 -0
- metadata +4 -6
data/README
CHANGED
@@ -5,6 +5,12 @@ SYNOPSIS
|
|
5
5
|
the ruby container you've always wanted: a string/symbol indifferent ordered
|
6
6
|
hash that works in all rubies
|
7
7
|
|
8
|
+
maps are rad ordered hashes that are both ordered, string/symbol
|
9
|
+
indifferent, and have all sorts of sweetness like recursive convertsion,
|
10
|
+
more robust implementation than HashWithIndifferentAccess, support for
|
11
|
+
struct like (map.foo) access, and support for option/keyword access which
|
12
|
+
avoids several nasty classes of errors in many ruby libraries
|
13
|
+
|
8
14
|
INSTALL
|
9
15
|
gem install map
|
10
16
|
|
@@ -13,8 +19,8 @@ URI
|
|
13
19
|
|
14
20
|
DESCRIPTION
|
15
21
|
|
16
|
-
# maps are ordered. constructing them in an ordered fashion builds
|
17
|
-
# way
|
22
|
+
# maps are always ordered. constructing them in an ordered fashion builds
|
23
|
+
# them that way, although the normal hash contructor is also supported
|
18
24
|
#
|
19
25
|
m = Map[:k, :v, :key, :val]
|
20
26
|
m = Map(:k, :v, :key, :val)
|
@@ -51,5 +57,35 @@ DESCRIPTION
|
|
51
57
|
s = m.struct
|
52
58
|
p s.foo.bar #=> 42
|
53
59
|
|
60
|
+
# because option parsing is such a common use case for needing string/symbol
|
61
|
+
# indifference map.rb comes out of the box for option support
|
62
|
+
#
|
63
|
+
def foo(*args, &block)
|
64
|
+
opts = Map.options(args)
|
65
|
+
a = opts.getopt(:a)
|
66
|
+
b = opts.getopt(:b, :default => false)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
opts = Map.options(:a => 42, :b => nil, :c => false)
|
71
|
+
opts.getopt(:a) #=> 42
|
72
|
+
opts.getopt(:b) #=> nil
|
73
|
+
opts.getopt(:b, :default => 42) #=> 42
|
74
|
+
opts.getopt(:c) #=> false
|
75
|
+
opts.getopt(:d, :default => false) #=> false
|
76
|
+
|
77
|
+
# this avoids such bugs as
|
78
|
+
#
|
79
|
+
options = {:read_only => true}
|
80
|
+
read_only = options[:read_only] || true # should be false but is true
|
81
|
+
|
82
|
+
# with options this becomes
|
83
|
+
#
|
84
|
+
options = Map.options(:read_only => true)
|
85
|
+
read_only = options.getopt(:read_only, :default => false) #=> true
|
86
|
+
|
87
|
+
# tons more goodness, see test/map_test.rb
|
88
|
+
#
|
89
|
+
|
54
90
|
USAGE
|
55
|
-
test/map_test.rb
|
91
|
+
again, see test/map_test.rb
|
data/lib/map.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Map < Hash
|
2
|
-
Version = '1.
|
2
|
+
Version = '1.5.0' unless defined?(Version)
|
3
3
|
Load = Kernel.method(:load) unless defined?(Load)
|
4
4
|
|
5
5
|
class << Map
|
@@ -452,3 +452,4 @@ private
|
|
452
452
|
end
|
453
453
|
|
454
454
|
Map.load('struct.rb')
|
455
|
+
Map.load('options.rb')
|
data/lib/map/options.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
class Map
|
2
|
+
module Options
|
3
|
+
class << Options
|
4
|
+
def for(arg)
|
5
|
+
hash =
|
6
|
+
case arg
|
7
|
+
when Hash
|
8
|
+
arg
|
9
|
+
when Array
|
10
|
+
parse(arg)
|
11
|
+
when String, Symbol
|
12
|
+
{arg => true}
|
13
|
+
else
|
14
|
+
raise(ArgumentError, arg.inspect) unless arg.respond_to?(:to_hash)
|
15
|
+
arg.to_hash
|
16
|
+
end
|
17
|
+
map = Map.coerce(hash)
|
18
|
+
ensure
|
19
|
+
map.extend(Options) unless map.is_a?(Options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse(arg)
|
23
|
+
case arg
|
24
|
+
when Array
|
25
|
+
arg.extend(Arguments) unless arg.is_a?(Arguments)
|
26
|
+
arg.options
|
27
|
+
when Hash
|
28
|
+
Options.for(arg)
|
29
|
+
else
|
30
|
+
raise(ArgumentError, "`arg` should be an Array or Hash")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :arguments
|
36
|
+
|
37
|
+
%w( to_options stringify_keys ).each do |method|
|
38
|
+
module_eval <<-__, __FILE__, __LINE__
|
39
|
+
def #{ method }() dup end
|
40
|
+
def #{ method }!() self end
|
41
|
+
__
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_opt(opts, options = {})
|
45
|
+
options = Map.for(options.is_a?(Hash) ? options : {:default => options})
|
46
|
+
default = options[:default]
|
47
|
+
[ opts ].flatten.each do |opt|
|
48
|
+
return fetch(opt) if has_key?(opt)
|
49
|
+
end
|
50
|
+
default
|
51
|
+
end
|
52
|
+
alias_method('getopt', 'get_opt')
|
53
|
+
|
54
|
+
def get_opts(*opts)
|
55
|
+
opts.flatten.map{|opt| getopt(opt)}
|
56
|
+
end
|
57
|
+
alias_method('getopts', 'get_opts')
|
58
|
+
|
59
|
+
def has_opt(opts)
|
60
|
+
[ opts ].flatten.each do |opt|
|
61
|
+
return true if has_key?(opt)
|
62
|
+
end
|
63
|
+
false
|
64
|
+
end
|
65
|
+
alias_method('hasopt', 'has_opt')
|
66
|
+
alias_method('hasopt?', 'has_opt')
|
67
|
+
alias_method('has_opt?', 'has_opt')
|
68
|
+
|
69
|
+
def has_opts(*opts)
|
70
|
+
opts.flatten.all?{|opt| hasopt(opt)}
|
71
|
+
end
|
72
|
+
alias_method('hasopts?', 'has_opts')
|
73
|
+
alias_method('has_opts?', 'has_opts')
|
74
|
+
|
75
|
+
def del_opt(opts)
|
76
|
+
[ opts ].flatten.each do |opt|
|
77
|
+
return delete(opt) if has_key?(opt)
|
78
|
+
end
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
alias_method('delopt', 'del_opt')
|
82
|
+
|
83
|
+
def del_opts(*opts)
|
84
|
+
opts.flatten.map{|opt| delopt(opt)}
|
85
|
+
opts
|
86
|
+
end
|
87
|
+
alias_method('delopts', 'del_opts')
|
88
|
+
alias_method('delopts!', 'del_opts')
|
89
|
+
|
90
|
+
def set_opt(opts, value = nil)
|
91
|
+
[ opts ].flatten.each do |opt|
|
92
|
+
return self[opt]=value
|
93
|
+
end
|
94
|
+
return value
|
95
|
+
end
|
96
|
+
alias_method('setopt', 'set_opt')
|
97
|
+
alias_method('setopt!', 'set_opt')
|
98
|
+
|
99
|
+
def set_opts(opts)
|
100
|
+
opts.each{|key, value| setopt(key, value)}
|
101
|
+
opts
|
102
|
+
end
|
103
|
+
alias_method('setopts', 'set_opts')
|
104
|
+
alias_method('setopts!', 'set_opts')
|
105
|
+
|
106
|
+
def pop
|
107
|
+
pop! unless popped?
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def popped?
|
112
|
+
defined?(@popped) and @popped
|
113
|
+
end
|
114
|
+
|
115
|
+
def pop!
|
116
|
+
if arguments.last.is_a?(Hash)
|
117
|
+
@popped = arguments.pop
|
118
|
+
else
|
119
|
+
@popped = true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
module Arguments
|
125
|
+
def options
|
126
|
+
@options ||= Options.for(last.is_a?(Hash) ? last : {})
|
127
|
+
ensure
|
128
|
+
@options.arguments = self
|
129
|
+
end
|
130
|
+
|
131
|
+
class << Arguments
|
132
|
+
def for(args)
|
133
|
+
args.extend(Arguments) unless args.is_a?(Arguments)
|
134
|
+
args
|
135
|
+
end
|
136
|
+
|
137
|
+
def parse(args)
|
138
|
+
[args, Options.parse(args)]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def Map.options(*args, &block)
|
146
|
+
Map::Options.for(*args, &block)
|
147
|
+
end
|
148
|
+
|
149
|
+
def Map.opts(*args, &block)
|
150
|
+
Map::Options.for(*args, &block)
|
151
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: map
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 7
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
8
|
-
-
|
7
|
+
- 5
|
9
8
|
- 0
|
10
|
-
version: 1.
|
9
|
+
version: 1.5.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Ara T. Howard
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-28 00:00:00 -06:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -29,6 +28,7 @@ extra_rdoc_files: []
|
|
29
28
|
|
30
29
|
files:
|
31
30
|
- a.rb
|
31
|
+
- lib/map/options.rb
|
32
32
|
- lib/map/struct.rb
|
33
33
|
- lib/map.rb
|
34
34
|
- Rakefile
|
@@ -50,7 +50,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
51
51
|
- - ">="
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
hash: 3
|
54
53
|
segments:
|
55
54
|
- 0
|
56
55
|
version: "0"
|
@@ -59,7 +58,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
58
|
requirements:
|
60
59
|
- - ">="
|
61
60
|
- !ruby/object:Gem::Version
|
62
|
-
hash: 3
|
63
61
|
segments:
|
64
62
|
- 0
|
65
63
|
version: "0"
|