rubymail 0.11
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.
- checksums.yaml +7 -0
- data/.gitignore +64 -0
- data/Gemfile +7 -0
- data/LICENSE +201 -0
- data/README.md +2 -0
- data/Rakefile +1 -0
- data/lib/multimap/.gitignore +4 -0
- data/lib/multimap/LICENSE +20 -0
- data/lib/multimap/README.rdoc +16 -0
- data/lib/multimap/Rakefile +34 -0
- data/lib/multimap/benchmarks/bm_nested_multimap_construction.rb +60 -0
- data/lib/multimap/benchmarks/bm_nested_multimap_lookup.rb +33 -0
- data/lib/multimap/ext/extconf.rb +6 -0
- data/lib/multimap/ext/nested_multimap_ext.c +24 -0
- data/lib/multimap/extras/graphing.rb +83 -0
- data/lib/multimap/lib/multimap.rb +569 -0
- data/lib/multimap/lib/multiset.rb +185 -0
- data/lib/multimap/lib/nested_multimap.rb +158 -0
- data/lib/multimap/spec/enumerable_examples.rb +50 -0
- data/lib/multimap/spec/hash_examples.rb +264 -0
- data/lib/multimap/spec/multimap_spec.rb +45 -0
- data/lib/multimap/spec/multiset_spec.rb +184 -0
- data/lib/multimap/spec/nested_multimap_spec.rb +202 -0
- data/lib/multimap/spec/set_examples.rb +301 -0
- data/lib/multimap/spec/spec_helper.rb +67 -0
- data/lib/rubymail/address.rb +17 -0
- data/lib/rubymail/base.rb +118 -0
- data/lib/rubymail/bounce.rb +31 -0
- data/lib/rubymail/client.rb +87 -0
- data/lib/rubymail/complaint.rb +31 -0
- data/lib/rubymail/domain.rb +34 -0
- data/lib/rubymail/list.rb +37 -0
- data/lib/rubymail/log.rb +19 -0
- data/lib/rubymail/mailbox.rb +41 -0
- data/lib/rubymail/message.rb +16 -0
- data/lib/rubymail/route.rb +99 -0
- data/lib/rubymail/rubymail_error.rb +53 -0
- data/lib/rubymail/secure.rb +19 -0
- data/lib/rubymail/unsubscribe.rb +31 -0
- data/lib/rubymail/webhook.rb +43 -0
- data/lib/rubymail.rb +31 -0
- data/rubymail.gemspec +18 -0
- data/spec/address_spec.rb +27 -0
- data/spec/base_spec.rb +132 -0
- data/spec/bounce_spec.rb +66 -0
- data/spec/client_spec.rb +118 -0
- data/spec/complaint_spec.rb +103 -0
- data/spec/domain_spec.rb +80 -0
- data/spec/helpers/rubymail_helper.rb +9 -0
- data/spec/list/member_spec.rb +82 -0
- data/spec/list/message_spec.rb +40 -0
- data/spec/list_spec.rb +70 -0
- data/spec/log_spec.rb +27 -0
- data/spec/mailbox_spec.rb +63 -0
- data/spec/route_spec.rb +100 -0
- data/spec/secure_spec.rb +54 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/unsubscribe_spec.rb +82 -0
- data/spec/webhook_spec.rb +115 -0
- metadata +159 -0
@@ -0,0 +1,569 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
require 'multimap/lib/multiset'
|
3
|
+
|
4
|
+
# Multimap is a generalization of a map or associative array
|
5
|
+
# abstract data type in which more than one value may be associated
|
6
|
+
# with and returned for a given key.
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# require 'multimap'
|
11
|
+
# map = Multimap.new
|
12
|
+
# map["a"] = 100
|
13
|
+
# map["b"] = 200
|
14
|
+
# map["a"] = 300
|
15
|
+
# map["a"] # -> [100, 300]
|
16
|
+
# map["b"] # -> [200]
|
17
|
+
# map.keys # -> #<Multiset: {a, a, b}>
|
18
|
+
class Multimap
|
19
|
+
extend Forwardable
|
20
|
+
|
21
|
+
include Enumerable
|
22
|
+
|
23
|
+
# call-seq:
|
24
|
+
# Multimap[ [key =>|, value]* ] => multimap
|
25
|
+
#
|
26
|
+
# Creates a new multimap populated with the given objects.
|
27
|
+
#
|
28
|
+
# Multimap["a", 100, "b", 200] #=> {"a"=>[100], "b"=>[200]}
|
29
|
+
# Multimap["a" => 100, "b" => 200] #=> {"a"=>[100], "b"=>[200]}
|
30
|
+
def self.[](*args)
|
31
|
+
default = []
|
32
|
+
|
33
|
+
if args.size == 2 && args.last.is_a?(Hash)
|
34
|
+
default = args.shift
|
35
|
+
elsif !args.first.is_a?(Hash) && args.size % 2 == 1
|
36
|
+
default = args.shift
|
37
|
+
end
|
38
|
+
|
39
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
40
|
+
args[0] = args.first.inject({}) { |hash, (key, value)|
|
41
|
+
unless value.is_a?(default.class)
|
42
|
+
value = (default.dup << value)
|
43
|
+
end
|
44
|
+
hash[key] = value
|
45
|
+
hash
|
46
|
+
}
|
47
|
+
else
|
48
|
+
index = 0
|
49
|
+
args.map! { |value|
|
50
|
+
unless index % 2 == 0 || value.is_a?(default.class)
|
51
|
+
value = (default.dup << value)
|
52
|
+
end
|
53
|
+
index += 1
|
54
|
+
value
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
map = new
|
59
|
+
map.instance_variable_set(:@hash, Hash[*args])
|
60
|
+
map.default = default
|
61
|
+
map
|
62
|
+
end
|
63
|
+
|
64
|
+
# call-seq:
|
65
|
+
# Multimap.new => multimap
|
66
|
+
# Multimap.new(default) => multimap
|
67
|
+
#
|
68
|
+
# Returns a new, empty multimap.
|
69
|
+
#
|
70
|
+
# map = Multimap.new(Set.new)
|
71
|
+
# h["a"] = 100
|
72
|
+
# h["b"] = 200
|
73
|
+
# h["a"] #=> [100].to_set
|
74
|
+
# h["c"] #=> [].to_set
|
75
|
+
def initialize(default = [])
|
76
|
+
@hash = Hash.new(default)
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize_copy(original) #:nodoc:
|
80
|
+
@hash = Hash.new(original.default.dup)
|
81
|
+
original._internal_hash.each_pair do |key, container|
|
82
|
+
@hash[key] = container.dup
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def_delegators :@hash, :clear, :default, :default=, :empty?,
|
87
|
+
:fetch, :has_key?, :key?
|
88
|
+
|
89
|
+
# Retrieves the <i>value</i> object corresponding to the
|
90
|
+
# <i>*keys</i> object.
|
91
|
+
def [](key)
|
92
|
+
@hash[key]
|
93
|
+
end
|
94
|
+
|
95
|
+
# call-seq:
|
96
|
+
# map[key] = value => value
|
97
|
+
# map.store(key, value) => value
|
98
|
+
#
|
99
|
+
# Associates the value given by <i>value</i> with the key
|
100
|
+
# given by <i>key</i>. Unlike a regular hash, multiple can be
|
101
|
+
# assoicated with the same value.
|
102
|
+
#
|
103
|
+
# map = Multimap["a" => 100, "b" => 200]
|
104
|
+
# map["a"] = 9
|
105
|
+
# map["c"] = 4
|
106
|
+
# map #=> {"a" => [100, 9], "b" => [200], "c" => [4]}
|
107
|
+
def store(key, value)
|
108
|
+
update_container(key) do |container|
|
109
|
+
container << value
|
110
|
+
container
|
111
|
+
end
|
112
|
+
end
|
113
|
+
alias_method :[]=, :store
|
114
|
+
|
115
|
+
# call-seq:
|
116
|
+
# map.delete(key, value) => value
|
117
|
+
# map.delete(key) => value
|
118
|
+
#
|
119
|
+
# Deletes and returns a key-value pair from <i>map</i>. If only
|
120
|
+
# <i>key</i> is given, all the values matching that key will be
|
121
|
+
# deleted.
|
122
|
+
#
|
123
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
124
|
+
# map.delete("b", 300) #=> 300
|
125
|
+
# map.delete("a") #=> [100]
|
126
|
+
def delete(key, value = nil)
|
127
|
+
if value
|
128
|
+
@hash[key].delete(value)
|
129
|
+
else
|
130
|
+
@hash.delete(key)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# call-seq:
|
135
|
+
# map.each { |key, value| block } => map
|
136
|
+
#
|
137
|
+
# Calls <i>block</i> for each key/value pair in <i>map</i>, passing
|
138
|
+
# the key and value to the block as a two-element array.
|
139
|
+
#
|
140
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
141
|
+
# map.each { |key, value| puts "#{key} is #{value}" }
|
142
|
+
#
|
143
|
+
# <em>produces:</em>
|
144
|
+
#
|
145
|
+
# a is 100
|
146
|
+
# b is 200
|
147
|
+
# b is 300
|
148
|
+
def each
|
149
|
+
each_pair do |key, value|
|
150
|
+
yield [key, value]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# call-seq:
|
155
|
+
# map.each_association { |key, container| block } => map
|
156
|
+
#
|
157
|
+
# Calls <i>block</i> once for each key/container in <i>map</i>, passing
|
158
|
+
# the key and container to the block as parameters.
|
159
|
+
#
|
160
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
161
|
+
# map.each_association { |key, container| puts "#{key} is #{container}" }
|
162
|
+
#
|
163
|
+
# <em>produces:</em>
|
164
|
+
#
|
165
|
+
# a is [100]
|
166
|
+
# b is [200, 300]
|
167
|
+
def each_association(&block)
|
168
|
+
@hash.each_pair(&block)
|
169
|
+
end
|
170
|
+
|
171
|
+
# call-seq:
|
172
|
+
# map.each_container { |container| block } => map
|
173
|
+
#
|
174
|
+
# Calls <i>block</i> for each container in <i>map</i>, passing the
|
175
|
+
# container as a parameter.
|
176
|
+
#
|
177
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
178
|
+
# map.each_container { |container| puts container }
|
179
|
+
#
|
180
|
+
# <em>produces:</em>
|
181
|
+
#
|
182
|
+
# [100]
|
183
|
+
# [200, 300]
|
184
|
+
def each_container
|
185
|
+
each_association do |_, container|
|
186
|
+
yield container
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# call-seq:
|
191
|
+
# map.each_key { |key| block } => map
|
192
|
+
#
|
193
|
+
# Calls <i>block</i> for each key in <i>hsh</i>, passing the key
|
194
|
+
# as a parameter.
|
195
|
+
#
|
196
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
197
|
+
# map.each_key { |key| puts key }
|
198
|
+
#
|
199
|
+
# <em>produces:</em>
|
200
|
+
#
|
201
|
+
# a
|
202
|
+
# b
|
203
|
+
# b
|
204
|
+
def each_key
|
205
|
+
each_pair do |key, _|
|
206
|
+
yield key
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# call-seq:
|
211
|
+
# map.each_pair { |key_value_array| block } => map
|
212
|
+
#
|
213
|
+
# Calls <i>block</i> for each key/value pair in <i>map</i>,
|
214
|
+
# passing the key and value as parameters.
|
215
|
+
#
|
216
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
217
|
+
# map.each_pair { |key, value| puts "#{key} is #{value}" }
|
218
|
+
#
|
219
|
+
# <em>produces:</em>
|
220
|
+
#
|
221
|
+
# a is 100
|
222
|
+
# b is 200
|
223
|
+
# b is 300
|
224
|
+
def each_pair
|
225
|
+
each_association do |key, values|
|
226
|
+
values.each do |value|
|
227
|
+
yield key, value
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
# call-seq:
|
233
|
+
# map.each_value { |value| block } => map
|
234
|
+
#
|
235
|
+
# Calls <i>block</i> for each key in <i>map</i>, passing the
|
236
|
+
# value as a parameter.
|
237
|
+
#
|
238
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
239
|
+
# map.each_value { |value| puts value }
|
240
|
+
#
|
241
|
+
# <em>produces:</em>
|
242
|
+
#
|
243
|
+
# 100
|
244
|
+
# 200
|
245
|
+
# 300
|
246
|
+
def each_value
|
247
|
+
each_pair do |_, value|
|
248
|
+
yield value
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def ==(other) #:nodoc:
|
253
|
+
case other
|
254
|
+
when Multimap
|
255
|
+
@hash == other._internal_hash
|
256
|
+
else
|
257
|
+
@hash == other
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def eql?(other) #:nodoc:
|
262
|
+
case other
|
263
|
+
when Multimap
|
264
|
+
@hash.eql?(other._internal_hash)
|
265
|
+
else
|
266
|
+
@hash.eql?(other)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def freeze #:nodoc:
|
271
|
+
each_container { |container| container.freeze }
|
272
|
+
default.freeze
|
273
|
+
super
|
274
|
+
end
|
275
|
+
|
276
|
+
# call-seq:
|
277
|
+
# map.has_value?(value) => true or false
|
278
|
+
# map.value?(value) => true or false
|
279
|
+
#
|
280
|
+
# Returns <tt>true</tt> if the given value is present for any key
|
281
|
+
# in <i>map</i>.
|
282
|
+
#
|
283
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
284
|
+
# map.has_value?(300) #=> true
|
285
|
+
# map.has_value?(999) #=> false
|
286
|
+
def has_value?(value)
|
287
|
+
values.include?(value)
|
288
|
+
end
|
289
|
+
alias_method :value?, :has_value?
|
290
|
+
|
291
|
+
# call-seq:
|
292
|
+
# map.index(value) => key
|
293
|
+
#
|
294
|
+
# Returns the key for a given value. If not found, returns
|
295
|
+
# <tt>nil</tt>.
|
296
|
+
#
|
297
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
298
|
+
# map.index(100) #=> "a"
|
299
|
+
# map.index(200) #=> "b"
|
300
|
+
# map.index(999) #=> nil
|
301
|
+
def index(value)
|
302
|
+
invert[value]
|
303
|
+
end
|
304
|
+
|
305
|
+
# call-seq:
|
306
|
+
# map.delete_if {| key, value | block } -> map
|
307
|
+
#
|
308
|
+
# Deletes every key-value pair from <i>map</i> for which <i>block</i>
|
309
|
+
# evaluates to <code>true</code>.
|
310
|
+
#
|
311
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
312
|
+
# map.delete_if {|key, value| value >= 300 }
|
313
|
+
# #=> Multimap["a" => 100, "b" => 200]
|
314
|
+
#
|
315
|
+
def delete_if
|
316
|
+
each_association do |key, container|
|
317
|
+
container.delete_if do |value|
|
318
|
+
yield [key, value]
|
319
|
+
end
|
320
|
+
end
|
321
|
+
self
|
322
|
+
end
|
323
|
+
|
324
|
+
# call-seq:
|
325
|
+
# map.reject {| key, value | block } -> map
|
326
|
+
#
|
327
|
+
# Same as <code>Multimap#delete_if</code>, but works on (and returns) a
|
328
|
+
# copy of the <i>map</i>. Equivalent to
|
329
|
+
# <code><i>map</i>.dup.delete_if</code>.
|
330
|
+
#
|
331
|
+
def reject(&block)
|
332
|
+
dup.delete_if(&block)
|
333
|
+
end
|
334
|
+
|
335
|
+
# call-seq:
|
336
|
+
# map.reject! {| key, value | block } -> map or nil
|
337
|
+
#
|
338
|
+
# Equivalent to <code>Multimap#delete_if</code>, but returns
|
339
|
+
# <code>nil</code> if no changes were made.
|
340
|
+
#
|
341
|
+
def reject!(&block)
|
342
|
+
old_size = size
|
343
|
+
delete_if(&block)
|
344
|
+
old_size == size ? nil : self
|
345
|
+
end
|
346
|
+
|
347
|
+
# call-seq:
|
348
|
+
# map.replace(other_map) => map
|
349
|
+
#
|
350
|
+
# Replaces the contents of <i>map</i> with the contents of
|
351
|
+
# <i>other_map</i>.
|
352
|
+
#
|
353
|
+
# map = Multimap["a" => 100, "b" => 200]
|
354
|
+
# map.replace({ "c" => 300, "d" => 400 })
|
355
|
+
# #=> Multimap["c" => 300, "d" => 400]
|
356
|
+
def replace(other)
|
357
|
+
case other
|
358
|
+
when Array
|
359
|
+
@hash.replace(self.class[self.default, *other])
|
360
|
+
when Hash
|
361
|
+
@hash.replace(self.class[self.default, other])
|
362
|
+
when self.class
|
363
|
+
@hash.replace(other)
|
364
|
+
else
|
365
|
+
raise ArgumentError
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
# call-seq:
|
370
|
+
# map.invert => multimap
|
371
|
+
#
|
372
|
+
# Returns a new multimap created by using <i>map</i>'s values as keys,
|
373
|
+
# and the keys as values.
|
374
|
+
#
|
375
|
+
# map = Multimap["n" => 100, "m" => 100, "d" => [200, 300]]
|
376
|
+
# map.invert #=> Multimap[100 => ["n", "m"], 200 => "d", 300 => "d"]
|
377
|
+
def invert
|
378
|
+
h = self.class.new(default.dup)
|
379
|
+
each_pair { |key, value| h[value] = key }
|
380
|
+
h
|
381
|
+
end
|
382
|
+
|
383
|
+
# call-seq:
|
384
|
+
# map.keys => multiset
|
385
|
+
#
|
386
|
+
# Returns a new +Multiset+ populated with the keys from this hash. See also
|
387
|
+
# <tt>Multimap#values</tt> and <tt>Multimap#containers</tt>.
|
388
|
+
#
|
389
|
+
# map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
|
390
|
+
# map.keys #=> Multiset.new(["a", "b", "b", "c"])
|
391
|
+
def keys
|
392
|
+
keys = Multiset.new
|
393
|
+
each_key { |key| keys << key }
|
394
|
+
keys
|
395
|
+
end
|
396
|
+
|
397
|
+
# Returns true if the given key is present in Multimap.
|
398
|
+
def include?(key)
|
399
|
+
keys.include?(key)
|
400
|
+
end
|
401
|
+
alias_method :member?, :include?
|
402
|
+
|
403
|
+
# call-seq:
|
404
|
+
# map.length => fixnum
|
405
|
+
# map.size => fixnum
|
406
|
+
#
|
407
|
+
# Returns the number of key-value pairs in the map.
|
408
|
+
#
|
409
|
+
# map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
|
410
|
+
# map.length #=> 4
|
411
|
+
# map.delete("a") #=> 100
|
412
|
+
# map.length #=> 3
|
413
|
+
def size
|
414
|
+
values.size
|
415
|
+
end
|
416
|
+
alias_method :length, :size
|
417
|
+
|
418
|
+
# call-seq:
|
419
|
+
# map.merge(other_map) => multimap
|
420
|
+
#
|
421
|
+
# Returns a new multimap containing the contents of <i>other_map</i> and
|
422
|
+
# the contents of <i>map</i>.
|
423
|
+
#
|
424
|
+
# map1 = Multimap["a" => 100, "b" => 200]
|
425
|
+
# map2 = Multimap["a" => 254, "c" => 300]
|
426
|
+
# map2.merge(map2) #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
|
427
|
+
# map1 #=> Multimap["a" => 100, "b" => 200]
|
428
|
+
def merge(other)
|
429
|
+
dup.update(other)
|
430
|
+
end
|
431
|
+
|
432
|
+
# call-seq:
|
433
|
+
# map.merge!(other_map) => multimap
|
434
|
+
# map.update(other_map) => multimap
|
435
|
+
#
|
436
|
+
# Adds each pair from <i>other_map</i> to <i>map</i>.
|
437
|
+
#
|
438
|
+
# map1 = Multimap["a" => 100, "b" => 200]
|
439
|
+
# map2 = Multimap["b" => 254, "c" => 300]
|
440
|
+
#
|
441
|
+
# map1.merge!(map2)
|
442
|
+
# #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
|
443
|
+
def update(other)
|
444
|
+
case other
|
445
|
+
when self.class
|
446
|
+
other.each_pair { |key, value| store(key, value) }
|
447
|
+
when Hash
|
448
|
+
update(self.class[self.default, other])
|
449
|
+
else
|
450
|
+
raise ArgumentError
|
451
|
+
end
|
452
|
+
self
|
453
|
+
end
|
454
|
+
alias_method :merge!, :update
|
455
|
+
|
456
|
+
# call-seq:
|
457
|
+
# map.select { |key, value| block } => multimap
|
458
|
+
#
|
459
|
+
# Returns a new Multimap consisting of the pairs for which the
|
460
|
+
# block returns true.
|
461
|
+
#
|
462
|
+
# map = Multimap["a" => 100, "b" => 200, "c" => 300]
|
463
|
+
# map.select { |k,v| k > "a" } #=> Multimap["b" => 200, "c" => 300]
|
464
|
+
# map.select { |k,v| v < 200 } #=> Multimap["a" => 100]
|
465
|
+
def select
|
466
|
+
inject(self.class.new) { |map, (key, value)|
|
467
|
+
map[key] = value if yield([key, value])
|
468
|
+
map
|
469
|
+
}
|
470
|
+
end
|
471
|
+
|
472
|
+
# call-seq:
|
473
|
+
# map.to_a => array
|
474
|
+
#
|
475
|
+
# Converts <i>map</i> to a nested array of [<i>key,
|
476
|
+
# value</i>] arrays.
|
477
|
+
#
|
478
|
+
# map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
|
479
|
+
# map.to_a #=> [["a", 100], ["b", 200], ["b", 300], ["c", 400]]
|
480
|
+
def to_a
|
481
|
+
ary = []
|
482
|
+
each_pair do |key, value|
|
483
|
+
ary << [key, value]
|
484
|
+
end
|
485
|
+
ary
|
486
|
+
end
|
487
|
+
|
488
|
+
# call-seq:
|
489
|
+
# map.to_hash => hash
|
490
|
+
#
|
491
|
+
# Converts <i>map</i> to a basic hash.
|
492
|
+
#
|
493
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
494
|
+
# map.to_hash #=> { "a" => [100], "b" => [200, 300] }
|
495
|
+
def to_hash
|
496
|
+
@hash.dup
|
497
|
+
end
|
498
|
+
|
499
|
+
# call-seq:
|
500
|
+
# map.containers => array
|
501
|
+
#
|
502
|
+
# Returns a new array populated with the containers from <i>map</i>. See
|
503
|
+
# also <tt>Multimap#keys</tt> and <tt>Multimap#values</tt>.
|
504
|
+
#
|
505
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
506
|
+
# map.containers #=> [[100], [200, 300]]
|
507
|
+
def containers
|
508
|
+
containers = []
|
509
|
+
each_container { |container| containers << container }
|
510
|
+
containers
|
511
|
+
end
|
512
|
+
|
513
|
+
# call-seq:
|
514
|
+
# map.values => array
|
515
|
+
#
|
516
|
+
# Returns a new array populated with the values from <i>map</i>. See
|
517
|
+
# also <tt>Multimap#keys</tt> and <tt>Multimap#containers</tt>.
|
518
|
+
#
|
519
|
+
# map = Multimap["a" => 100, "b" => [200, 300]]
|
520
|
+
# map.values #=> [100, 200, 300]
|
521
|
+
def values
|
522
|
+
values = []
|
523
|
+
each_value { |value| values << value }
|
524
|
+
values
|
525
|
+
end
|
526
|
+
|
527
|
+
# Return an array containing the values associated with the given keys.
|
528
|
+
def values_at(*keys)
|
529
|
+
@hash.values_at(*keys)
|
530
|
+
end
|
531
|
+
|
532
|
+
def marshal_dump #:nodoc:
|
533
|
+
@hash
|
534
|
+
end
|
535
|
+
|
536
|
+
def marshal_load(hash) #:nodoc:
|
537
|
+
@hash = hash
|
538
|
+
end
|
539
|
+
|
540
|
+
def to_yaml(opts = {}) #:nodoc:
|
541
|
+
YAML::quick_emit(self, opts) do |out|
|
542
|
+
out.map(taguri, to_yaml_style) do |map|
|
543
|
+
@hash.each do |k, v|
|
544
|
+
map.add(k, v)
|
545
|
+
end
|
546
|
+
map.add('__default__', @hash.default)
|
547
|
+
end
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
551
|
+
def yaml_initialize(tag, val) #:nodoc:
|
552
|
+
default = val.delete('__default__')
|
553
|
+
@hash = val
|
554
|
+
@hash.default = default
|
555
|
+
self
|
556
|
+
end
|
557
|
+
|
558
|
+
protected
|
559
|
+
def _internal_hash #:nodoc:
|
560
|
+
@hash
|
561
|
+
end
|
562
|
+
|
563
|
+
def update_container(key) #:nodoc:
|
564
|
+
container = @hash[key]
|
565
|
+
container = container.dup if container.equal?(default)
|
566
|
+
container = yield(container)
|
567
|
+
@hash[key] = container
|
568
|
+
end
|
569
|
+
end
|