glue 0.13.0 → 0.14.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/CHANGELOG +19 -0
- data/README +1 -1
- data/Rakefile +1 -1
- data/doc/RELEASES +4 -0
- data/lib/glue.rb +6 -2
- data/lib/glue/attribute.rb +3 -0
- data/lib/glue/inflector.rb +1 -1
- data/lib/glue/logger.rb +29 -4
- data/lib/glue/property.rb +50 -46
- data/test/glue/tc_property.rb +8 -1
- data/vendor/README +11 -0
- data/vendor/binding_of_caller.rb +81 -0
- data/vendor/blankslate.rb +53 -0
- data/vendor/breakpoint.rb +523 -0
- data/vendor/breakpoint_client.rb +196 -0
- data/vendor/extensions/_base.rb +153 -0
- data/vendor/extensions/_template.rb +36 -0
- data/vendor/extensions/all.rb +21 -0
- data/vendor/extensions/array.rb +68 -0
- data/vendor/extensions/binding.rb +224 -0
- data/vendor/extensions/class.rb +50 -0
- data/vendor/extensions/continuation.rb +71 -0
- data/vendor/extensions/enumerable.rb +250 -0
- data/vendor/extensions/hash.rb +23 -0
- data/vendor/extensions/io.rb +58 -0
- data/vendor/extensions/kernel.rb +42 -0
- data/vendor/extensions/module.rb +114 -0
- data/vendor/extensions/numeric.rb +230 -0
- data/vendor/extensions/object.rb +164 -0
- data/vendor/extensions/ostruct.rb +41 -0
- data/vendor/extensions/string.rb +316 -0
- data/vendor/extensions/symbol.rb +28 -0
- metadata +26 -3
@@ -0,0 +1,224 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/binding.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Binding class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
require "extensions/continuation"
|
10
|
+
|
11
|
+
#
|
12
|
+
# Ruby's built-in Binding class doesn't contain any methods. It is merely a "context" object
|
13
|
+
# that can be used in calls to <tt>Kernel.eval</tt>, like this:
|
14
|
+
#
|
15
|
+
# def example(_binding)
|
16
|
+
# return eval("x", _binding)
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# x = 55
|
20
|
+
# current_binding = Kernel.binding
|
21
|
+
# example(current_binding) # -> 55
|
22
|
+
#
|
23
|
+
# The most useful method introduced to Binding by the _extensions_ package is
|
24
|
+
# Binding.of_caller. It allows you to access the binding of the calling method, thus
|
25
|
+
# enabling you to access local variables in that scope. The other methods are a convenient
|
26
|
+
# object-oriented facade for operations that you can already do with #eval as demonstrated
|
27
|
+
# above. Here is an example that showcases all of the Binding methods included in
|
28
|
+
# _extensions_.
|
29
|
+
#
|
30
|
+
# def example
|
31
|
+
# Binding.of_caller do |b|
|
32
|
+
# puts "x + y = #{b.eval('x + y')}"
|
33
|
+
# puts "x = #{b[:x]}"
|
34
|
+
# puts "Local variables: " + b.local_variables.join(', ')
|
35
|
+
# b[:y] += 1
|
36
|
+
# puts "Changed value of y in calling context to #{b[:y]}"
|
37
|
+
# puts "Is 'z' defined in calling context? " + (b.defined?(:z) ? 'Yes' : 'No')
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# x = 5
|
42
|
+
# y = 17
|
43
|
+
# example
|
44
|
+
# y # -> 18
|
45
|
+
#
|
46
|
+
# Binding.of_caller was written by Florian Gross. The other methods were written by Tom
|
47
|
+
# Sawyer.
|
48
|
+
#
|
49
|
+
class Binding
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# * Binding.of_caller
|
54
|
+
#
|
55
|
+
ExtensionsProject.implement(Binding, :of_caller, :class) do
|
56
|
+
class Binding
|
57
|
+
#
|
58
|
+
# This method returns the binding of the method that called your method, enabling you to
|
59
|
+
# access its local variables. If you call it without being in a method, it will raise an
|
60
|
+
# Exception.
|
61
|
+
#
|
62
|
+
# === Example
|
63
|
+
#
|
64
|
+
# def inc_counter
|
65
|
+
# Binding.of_caller do |b|
|
66
|
+
# eval("counter += 1", b)
|
67
|
+
# end
|
68
|
+
# # <--- line (A)
|
69
|
+
# end
|
70
|
+
# counter = 0
|
71
|
+
# inc_counter
|
72
|
+
# inc_counter
|
73
|
+
# counter # -> 2
|
74
|
+
#
|
75
|
+
# === Warning
|
76
|
+
#
|
77
|
+
# <tt>Binding.of_caller</tt> must be the _last_ method call in the method. For example,
|
78
|
+
# if you insert some code at line *A* in the example above, an Exception will be raised.
|
79
|
+
# You'll get away with a simple assignment, but anything involving a method call is
|
80
|
+
# trouble.
|
81
|
+
#
|
82
|
+
# === Explanation
|
83
|
+
#
|
84
|
+
# It works by installing a temporary trace_func (see Kernel.set_trace_func). This makes
|
85
|
+
# available -- to the trace function -- the binding of a method after it has returned.
|
86
|
+
# Using a continuation, <tt>Binding.of_caller</tt> will let _your_ method return,
|
87
|
+
# retrieve the binding, and return to the <tt>of_caller</tt> call with that binding in
|
88
|
+
# hand. This time it executes the block.
|
89
|
+
#
|
90
|
+
# Because it is actually running <tt>Binding.of_caller</tt> twice, and returning from
|
91
|
+
# your method twice, any code between the <tt>of_caller</tt> call and the end of your
|
92
|
+
# method will be run twice. This is obviously not desirable, so an Exception is raised
|
93
|
+
# if any code is found.
|
94
|
+
#
|
95
|
+
# See the thread around ruby-talk:109607 for more discussion.
|
96
|
+
#
|
97
|
+
# === Extra Warning
|
98
|
+
#
|
99
|
+
# If you have a trace function in place, <tt>Binding.of_caller</tt> will destroy that.
|
100
|
+
# Ruby does not allow you to access the current trace function, so it can't be restored
|
101
|
+
# afterwards. XXX: will this clash with the profiler and/or debugger?
|
102
|
+
#
|
103
|
+
# === Credits
|
104
|
+
#
|
105
|
+
# <tt>Binding.of_caller</tt> was written by Florian Frank.
|
106
|
+
#
|
107
|
+
def Binding.of_caller(&block)
|
108
|
+
old_critical = Thread.critical
|
109
|
+
Thread.critical = true
|
110
|
+
count = 0
|
111
|
+
cc, result, error = Continuation.create(nil, nil)
|
112
|
+
error.call if error
|
113
|
+
|
114
|
+
tracer = lambda do |*args|
|
115
|
+
type, context = args[0], args[4]
|
116
|
+
if type == "return"
|
117
|
+
count += 1
|
118
|
+
# First this method and then calling one will return --
|
119
|
+
# the trace event of the second event gets the context
|
120
|
+
# of the method which called the method that called this
|
121
|
+
# method.
|
122
|
+
if count == 2
|
123
|
+
# It would be nice if we could restore the trace_func
|
124
|
+
# that was set before we swapped in our own one, but
|
125
|
+
# this is impossible without overloading set_trace_func
|
126
|
+
# in current Ruby.
|
127
|
+
set_trace_func(nil)
|
128
|
+
cc.call(eval("binding", context), nil)
|
129
|
+
end
|
130
|
+
elsif type != "line"
|
131
|
+
set_trace_func(nil)
|
132
|
+
error_msg = "Binding.of_caller used in non-method context or " +
|
133
|
+
"trailing statements of method using it aren't in the block."
|
134
|
+
cc.call(nil, lambda { raise(Exception, error_msg ) })
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
unless result
|
139
|
+
set_trace_func(tracer)
|
140
|
+
return nil
|
141
|
+
else
|
142
|
+
Thread.critical = old_critical
|
143
|
+
yield result
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end # class Binding
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
#
|
151
|
+
# * Binding#eval
|
152
|
+
#
|
153
|
+
ExtensionsProject.implement(Binding, :eval, :instance) do
|
154
|
+
class Binding
|
155
|
+
#
|
156
|
+
# Evaluates the given string in the context of this binding.
|
157
|
+
#
|
158
|
+
def eval(str)
|
159
|
+
Kernel.eval(str, self)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
#
|
166
|
+
# * Binding#local_variables
|
167
|
+
#
|
168
|
+
ExtensionsProject.implement(Binding, :local_variables, :instance) do
|
169
|
+
class Binding
|
170
|
+
#
|
171
|
+
# Returns the variables that are local to this binding.
|
172
|
+
#
|
173
|
+
def local_variables
|
174
|
+
self.eval('local_variables')
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
#
|
181
|
+
# * Binding#[]
|
182
|
+
#
|
183
|
+
ExtensionsProject.implement(Binding, :[], :instance) do
|
184
|
+
class Binding
|
185
|
+
#
|
186
|
+
# Returns the value of the given variable in this binding.
|
187
|
+
#
|
188
|
+
def [](variable)
|
189
|
+
self.eval(variable.to_s)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
#
|
196
|
+
# * Binding#[]=
|
197
|
+
#
|
198
|
+
ExtensionsProject.implement(Binding, :[]=, :instance) do
|
199
|
+
class Binding
|
200
|
+
#
|
201
|
+
# Sets the given variable (in this binding) to the given value.
|
202
|
+
#
|
203
|
+
def []=(variable, value)
|
204
|
+
self.eval("lambda { |v| #{variable} = v }").call(value)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
#
|
211
|
+
# * Binding#defined?
|
212
|
+
#
|
213
|
+
ExtensionsProject.implement(Binding, :defined?, :instance) do
|
214
|
+
class Binding
|
215
|
+
#
|
216
|
+
# Evaluates <tt>defined?</tt> in this binding.
|
217
|
+
#
|
218
|
+
def defined?(variable)
|
219
|
+
self.eval("defined?(#{variable})")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/class.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Class class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
ExtensionsProject.implement(Class, :autoinit) do
|
11
|
+
class Class
|
12
|
+
#
|
13
|
+
# A shorthand for the common chore of assigning initialize's parameters to
|
14
|
+
# instance variables. For example:
|
15
|
+
#
|
16
|
+
# class Circle
|
17
|
+
#
|
18
|
+
# attr_reader :radius, :location, :area
|
19
|
+
#
|
20
|
+
# autoinit(:radius, :location) do
|
21
|
+
# @area = Math::PI * @radius ** 2
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# A TypeError is raised unless all the arguments to +autoinit+ are strings
|
27
|
+
# or symbols.
|
28
|
+
#
|
29
|
+
#--
|
30
|
+
# Taken from ruby-talk:11668, by Avi Bryant.
|
31
|
+
def autoinit(*args, &block) # :yield:
|
32
|
+
unless args.all? { |a| Symbol === a or String === a }
|
33
|
+
raise TypeError, "All arguments must be symbols or strings"
|
34
|
+
end
|
35
|
+
block = proc {} if block.nil?
|
36
|
+
define_method(:__init_proc) { block }
|
37
|
+
params = args.join(", ")
|
38
|
+
vars = args.map { |a| "@#{a}" }.join(", ")
|
39
|
+
|
40
|
+
code = %{
|
41
|
+
def initialize(#{params})
|
42
|
+
#{vars} = #{params}
|
43
|
+
instance_eval(&__init_proc)
|
44
|
+
end
|
45
|
+
}
|
46
|
+
class_eval code
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/continuation.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Continuation class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
#
|
11
|
+
# * Continuation.create
|
12
|
+
#
|
13
|
+
ExtensionsProject.implement(Continuation, :create, :class) do
|
14
|
+
class Continuation
|
15
|
+
#
|
16
|
+
# <tt>Continuation.create</tt> offers a nicer interface for creating continuations than
|
17
|
+
# <tt>Kernel.callcc</tt>.
|
18
|
+
#
|
19
|
+
# === Example
|
20
|
+
#
|
21
|
+
# Count down from 10 to 0 using a continuation.
|
22
|
+
#
|
23
|
+
# continuation, counter = Continuation.create(10)
|
24
|
+
# puts counter
|
25
|
+
# continuation.call(counter - 1) if counter > 0
|
26
|
+
#
|
27
|
+
# Implement a workalike of <tt>Array#inject</tt> using continuations. For simplicity's
|
28
|
+
# sake, this is not fully compatible with the real <tt>#inject</tt>.
|
29
|
+
#
|
30
|
+
# class Array
|
31
|
+
# def cc_inject( value=nil )
|
32
|
+
# copy = self.clone
|
33
|
+
# cc, result, item = Continuation.create( value, nil )
|
34
|
+
# next_item = copy.shift
|
35
|
+
# if result and item
|
36
|
+
# cc.call( yield(result, item), next_item )
|
37
|
+
# elsif next_item
|
38
|
+
# cc.call( next_item, result )
|
39
|
+
# end
|
40
|
+
# result
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# [1,2,3,4,5].cc_inject { |acc, n| acc + n } # -> 15
|
45
|
+
#
|
46
|
+
# === Explanation
|
47
|
+
#
|
48
|
+
# I've got no idea how it works. TODO: work it out. In particular, what do the arguments
|
49
|
+
# do? And what the hell is going on in #cc_inject???!?
|
50
|
+
#
|
51
|
+
# === See Also
|
52
|
+
#
|
53
|
+
# This method is included in the 'extensions' package primarily to support
|
54
|
+
# Binding.of_caller.
|
55
|
+
#
|
56
|
+
# === Credits
|
57
|
+
#
|
58
|
+
# <tt>Continuation.create</tt> was written and demonstrated by Florian Gross. See
|
59
|
+
# ruby-talk:94681.
|
60
|
+
#
|
61
|
+
def Continuation.create(*args, &block)
|
62
|
+
cc = nil
|
63
|
+
result = callcc { |c|
|
64
|
+
cc = c
|
65
|
+
block.call(cc) if block and args.empty?
|
66
|
+
}
|
67
|
+
result ||= args
|
68
|
+
return *[cc, *result]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,250 @@
|
|
1
|
+
#
|
2
|
+
# == extensions/enumerable.rb
|
3
|
+
#
|
4
|
+
# Adds methods to the builtin Enumerable module.
|
5
|
+
#
|
6
|
+
|
7
|
+
require "extensions/_base"
|
8
|
+
|
9
|
+
#
|
10
|
+
# * Enumerable#build_hash
|
11
|
+
#
|
12
|
+
ExtensionsProject.implement(Enumerable, :build_hash) do
|
13
|
+
module Enumerable
|
14
|
+
#
|
15
|
+
# Like <tt>#map</tt>/<tt>#collect</tt>, but it generates a Hash. The block
|
16
|
+
# is expected to return two values: the key and the value for the new hash.
|
17
|
+
# numbers = (1..3)
|
18
|
+
# squares = numbers.build_hash { |n| [n, n*n] } # 1=>1, 2=>4, 3=>9
|
19
|
+
# sq_roots = numbers.build_hash { |n| [n*n, n] } # 1=>1, 4=>2, 9=>3
|
20
|
+
#
|
21
|
+
def build_hash
|
22
|
+
result = {}
|
23
|
+
self.each do |elt|
|
24
|
+
key, value = yield elt
|
25
|
+
result[key] = value
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# There was a bug in Hash which causes the above code to issue a warning when
|
32
|
+
# used with a Hash. That was fixed on 2003-10-24.
|
33
|
+
if RUBY_RELEASE_DATE < "2003-10-25"
|
34
|
+
class Hash #:nodoc:
|
35
|
+
def build_hash
|
36
|
+
result = {}
|
37
|
+
self.each_pair do |k, v|
|
38
|
+
key, value = yield(k, v)
|
39
|
+
result[key] = value
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Enumerable#mapf
|
50
|
+
#
|
51
|
+
ExtensionsProject.implement(Enumerable, :mapf) do
|
52
|
+
module Enumerable
|
53
|
+
#
|
54
|
+
# "map function"
|
55
|
+
# enum.mapf(:x)
|
56
|
+
# is short for
|
57
|
+
# enum.map { |elt| elt.x }
|
58
|
+
#
|
59
|
+
def mapf(message)
|
60
|
+
self.map { |elt| elt.send(message) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
#
|
67
|
+
# Enumerable#collectf
|
68
|
+
#
|
69
|
+
ExtensionsProject.implement(Enumerable, :collectf) do
|
70
|
+
module Enumerable
|
71
|
+
alias collectf mapf
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
#
|
77
|
+
# * Enumerable#includes?
|
78
|
+
#
|
79
|
+
ExtensionsProject.implement(Enumerable, :includes?) do
|
80
|
+
module Enumerable
|
81
|
+
alias includes? include?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
#
|
87
|
+
# * Enumerable#contains?
|
88
|
+
#
|
89
|
+
ExtensionsProject.implement(Enumerable, :contains?) do
|
90
|
+
module Enumerable
|
91
|
+
alias contains? include?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
#
|
97
|
+
# * Enumerable#has?
|
98
|
+
#
|
99
|
+
ExtensionsProject.implement(Enumerable, :has?) do
|
100
|
+
module Enumerable
|
101
|
+
alias has? include?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
#
|
107
|
+
# * Enumerable#map_with_index
|
108
|
+
#
|
109
|
+
ExtensionsProject.implement(Enumerable, :map_with_index) do
|
110
|
+
module Enumerable
|
111
|
+
#
|
112
|
+
# Same as Enumerable#map, but the index is yielded as well. See
|
113
|
+
# Enumerable#each_with_index.
|
114
|
+
# puts files.map_with_index { |fn, idx| "#{idx}. #{fn}" }
|
115
|
+
# print "Please select a file (0-#{files.size}): "
|
116
|
+
#
|
117
|
+
def map_with_index
|
118
|
+
result = []
|
119
|
+
self.each_with_index do |elt, idx|
|
120
|
+
result << yield(elt, idx)
|
121
|
+
end
|
122
|
+
result
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
#
|
129
|
+
# * Enumerable#collect_with_index
|
130
|
+
#
|
131
|
+
ExtensionsProject.implement(Enumerable, :collect_with_index) do
|
132
|
+
module Enumerable
|
133
|
+
alias collect_with_index map_with_index
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
#
|
139
|
+
# * Enumerable#partition_by
|
140
|
+
#
|
141
|
+
ExtensionsProject.implement(Enumerable, :partition_by) do
|
142
|
+
module Enumerable
|
143
|
+
#
|
144
|
+
# See Enumerable#partition for the background. #partition_by is best
|
145
|
+
# explained by example.
|
146
|
+
#
|
147
|
+
# (1..5).partition_by { |n| n % 3 }
|
148
|
+
# # -> { 0 => [3], 1 => [1, 4], 2 => [2,5] }
|
149
|
+
#
|
150
|
+
# ["I had", 1, "dollar and", 50, "cents"].partition_by { |e| e.class }
|
151
|
+
# # -> { String => ["I had","dollar and","cents"], Fixnum => [1,50] }
|
152
|
+
#
|
153
|
+
# #partition_by is used to group items in a collection by something they
|
154
|
+
# have in common. The common factor is the key in the resulting hash, the
|
155
|
+
# array of like elements is the value.
|
156
|
+
#
|
157
|
+
def partition_by
|
158
|
+
result = {}
|
159
|
+
self.each do |e|
|
160
|
+
value = yield e
|
161
|
+
(result[value] ||= []) << e
|
162
|
+
end
|
163
|
+
result
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
#
|
170
|
+
# * Enumerable#none?
|
171
|
+
#
|
172
|
+
ExtensionsProject.implement(Enumerable, :none?) do
|
173
|
+
module Enumerable
|
174
|
+
#
|
175
|
+
# Enumerable#none? is the logical opposite of the builtin method Enumerable#any?. It
|
176
|
+
# returns +true+ if and only if _none_ of the elements in the collection satisfy the
|
177
|
+
# predicate.
|
178
|
+
#
|
179
|
+
# If no predicate is provided, Enumerable#none? returns +true+ if and only if _none_ of the
|
180
|
+
# elements have a true value (i.e. not +nil+ or +false+).
|
181
|
+
#
|
182
|
+
# [].none? # true
|
183
|
+
# [nil].none? # true
|
184
|
+
# [5,8,9].none? # false
|
185
|
+
# (1...10).none? { |n| n < 0 } # true
|
186
|
+
# (1...10).none? { |n| n > 0 } # false
|
187
|
+
#
|
188
|
+
def none? # :yield: e
|
189
|
+
if block_given?
|
190
|
+
not self.any? { |e| yield e }
|
191
|
+
else
|
192
|
+
not self.any?
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
#
|
200
|
+
# * Enumerable#one?
|
201
|
+
#
|
202
|
+
ExtensionsProject.implement(Enumerable, :one?) do
|
203
|
+
module Enumerable
|
204
|
+
#
|
205
|
+
# Enumerable#one? returns +true+ if and only if <em>exactly one</em> element in the
|
206
|
+
# collection satisfies the given predicate.
|
207
|
+
#
|
208
|
+
# If no predicate is provided, Enumerable#one? returns +true+ if and only if <em>exactly
|
209
|
+
# one</em> element has a true value (i.e. not +nil+ or +false+).
|
210
|
+
#
|
211
|
+
# [].one? # false
|
212
|
+
# [nil].one? # false
|
213
|
+
# [5].one? # true
|
214
|
+
# [5,8,9].one? # false
|
215
|
+
# (1...10).one? { |n| n == 5 } # true
|
216
|
+
# (1...10).one? { |n| n < 5 } # false
|
217
|
+
#
|
218
|
+
def one? # :yield: e
|
219
|
+
matches = 0
|
220
|
+
if block_given?
|
221
|
+
self.each do |e|
|
222
|
+
if yield(e)
|
223
|
+
matches += 1
|
224
|
+
return false if matches > 1
|
225
|
+
end
|
226
|
+
end
|
227
|
+
return (matches == 1)
|
228
|
+
else
|
229
|
+
one? { |e| e }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
#
|
237
|
+
# * Object.in?
|
238
|
+
# This has special treatment: it's included here and in object.rb, so we don't
|
239
|
+
# want a warning if it's alredy defined.
|
240
|
+
#
|
241
|
+
unless Object.method_defined?(:in?)
|
242
|
+
ExtensionsProject.implement(Object, :in?) do
|
243
|
+
class Object
|
244
|
+
def in?(enumerable) # :nodoc: It's documented in object.rb.
|
245
|
+
enumerable.include?(self)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|