backports 1.6.8 → 1.7.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/.document +5 -0
- data/.gitignore +7 -0
- data/CHANGELOG.rdoc +8 -0
- data/VERSION.yml +2 -2
- data/backports.gemspec +98 -0
- data/lib/backports.rb +1 -8
- data/lib/backports/argf.rb +57 -0
- data/lib/backports/array.rb +92 -59
- data/lib/backports/binding.rb +1 -1
- data/lib/backports/core_ext.rb +61 -0
- data/lib/backports/enumerable.rb +93 -56
- data/lib/backports/enumerator.rb +8 -6
- data/lib/backports/env.rb +3 -0
- data/lib/backports/fixnum.rb +1 -1
- data/lib/backports/float.rb +4 -0
- data/lib/backports/gc.rb +9 -0
- data/lib/backports/hash.rb +19 -17
- data/lib/backports/integer.rb +4 -13
- data/lib/backports/io.rb +44 -2
- data/lib/backports/kernel.rb +43 -8
- data/lib/backports/module.rb +0 -20
- data/lib/backports/numeric.rb +3 -0
- data/lib/backports/object_space.rb +0 -1
- data/lib/backports/proc.rb +1 -1
- data/lib/backports/process.rb +5 -0
- data/lib/backports/string.rb +26 -26
- data/lib/backports/symbol.rb +1 -1
- data/test/enumerable_test.rb +1 -1
- data/test/enumerator_test.rb +9 -0
- data/test/kernel_test.rb +6 -5
- metadata +12 -3
- data/lib/backports/object.rb +0 -37
data/.document
ADDED
data/.gitignore
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
= Packable --- History
|
2
2
|
|
3
|
+
== Version 1.7 - May 27, 2009
|
4
|
+
|
5
|
+
Porting all 1.8.7 features to rubinius was quite enlightening (http://blog.marc-andre.ca/2009/05/schizo-ruby-puzzle.html ).
|
6
|
+
Many improvements were made to be consistent with MRI, e.g. converting arguments using to_int if needed, etc...
|
7
|
+
The changes are now reflected in 'backports'.
|
8
|
+
|
9
|
+
Some IO and ARGF methods were missing and are now complete.
|
10
|
+
|
3
11
|
== Version 1.6.6 - April 30, 2009
|
4
12
|
|
5
13
|
Important bug fix. String#gsub is left alone until I find a good way to modify it.
|
data/VERSION.yml
CHANGED
data/backports.gemspec
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{backports}
|
5
|
+
s.version = "1.7.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Marc-Andr\303\251 Lafortune"]
|
9
|
+
s.date = %q{2009-05-31}
|
10
|
+
s.description = %q{Essential backports that enable some of the really nice features of ruby 1.8.7, ruby 1.9 and rails from ruby 1.8.6 and earlier.}
|
11
|
+
s.email = %q{github@marc-andre.ca}
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"LICENSE",
|
14
|
+
"README.rdoc"
|
15
|
+
]
|
16
|
+
s.files = [
|
17
|
+
".document",
|
18
|
+
".gitignore",
|
19
|
+
"CHANGELOG.rdoc",
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"VERSION.yml",
|
24
|
+
"backports.gemspec",
|
25
|
+
"lib/backports.rb",
|
26
|
+
"lib/backports/argf.rb",
|
27
|
+
"lib/backports/array.rb",
|
28
|
+
"lib/backports/binding.rb",
|
29
|
+
"lib/backports/core_ext.rb",
|
30
|
+
"lib/backports/dir.rb",
|
31
|
+
"lib/backports/enumerable.rb",
|
32
|
+
"lib/backports/enumerator.rb",
|
33
|
+
"lib/backports/env.rb",
|
34
|
+
"lib/backports/fixnum.rb",
|
35
|
+
"lib/backports/float.rb",
|
36
|
+
"lib/backports/gc.rb",
|
37
|
+
"lib/backports/hash.rb",
|
38
|
+
"lib/backports/integer.rb",
|
39
|
+
"lib/backports/io.rb",
|
40
|
+
"lib/backports/kernel.rb",
|
41
|
+
"lib/backports/method.rb",
|
42
|
+
"lib/backports/module.rb",
|
43
|
+
"lib/backports/numeric.rb",
|
44
|
+
"lib/backports/object_space.rb",
|
45
|
+
"lib/backports/proc.rb",
|
46
|
+
"lib/backports/process.rb",
|
47
|
+
"lib/backports/range.rb",
|
48
|
+
"lib/backports/regexp.rb",
|
49
|
+
"lib/backports/string.rb",
|
50
|
+
"lib/backports/struct.rb",
|
51
|
+
"lib/backports/symbol.rb",
|
52
|
+
"test/array_test.rb",
|
53
|
+
"test/binding_test.rb",
|
54
|
+
"test/enumerable_test.rb",
|
55
|
+
"test/enumerator_test.rb",
|
56
|
+
"test/hash_test.rb",
|
57
|
+
"test/kernel_test.rb",
|
58
|
+
"test/method_test.rb",
|
59
|
+
"test/module_test.rb",
|
60
|
+
"test/object_test.rb",
|
61
|
+
"test/regexp_test.rb",
|
62
|
+
"test/string_test.rb",
|
63
|
+
"test/symbol_test.rb",
|
64
|
+
"test/test_helper.rb"
|
65
|
+
]
|
66
|
+
s.has_rdoc = true
|
67
|
+
s.homepage = %q{http://github.com/marcandre/backports}
|
68
|
+
s.rdoc_options = ["--charset=UTF-8", "--title", "Backports library", "--main", "README.rdoc", "--line-numbers", "--inline-source"]
|
69
|
+
s.require_paths = ["lib"]
|
70
|
+
s.rubyforge_project = %q{backports}
|
71
|
+
s.rubygems_version = %q{1.3.1}
|
72
|
+
s.summary = %q{Backports or ruby 1.8.7+ & rails for older ruby.}
|
73
|
+
s.test_files = [
|
74
|
+
"test/array_test.rb",
|
75
|
+
"test/binding_test.rb",
|
76
|
+
"test/enumerable_test.rb",
|
77
|
+
"test/enumerator_test.rb",
|
78
|
+
"test/hash_test.rb",
|
79
|
+
"test/kernel_test.rb",
|
80
|
+
"test/method_test.rb",
|
81
|
+
"test/module_test.rb",
|
82
|
+
"test/object_test.rb",
|
83
|
+
"test/regexp_test.rb",
|
84
|
+
"test/string_test.rb",
|
85
|
+
"test/symbol_test.rb",
|
86
|
+
"test/test_helper.rb"
|
87
|
+
]
|
88
|
+
|
89
|
+
if s.respond_to? :specification_version then
|
90
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
91
|
+
s.specification_version = 2
|
92
|
+
|
93
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
94
|
+
else
|
95
|
+
end
|
96
|
+
else
|
97
|
+
end
|
98
|
+
end
|
data/lib/backports.rb
CHANGED
@@ -10,13 +10,6 @@ module Kernel
|
|
10
10
|
end unless method_defined? :require_relative
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
# Standard in rails, and we use it in module.
|
15
|
-
def extract_options!
|
16
|
-
last.is_a?(::Hash) ? pop : {}
|
17
|
-
end unless method_defined? :extract_options!
|
18
|
-
end
|
19
|
-
|
20
|
-
%w(object module kernel object_space array enumerable enumerator string symbol integer fixnum hash proc binding dir io method regexp struct).each do |lib|
|
13
|
+
%w(core_ext module kernel array enumerable enumerator string symbol integer numeric fixnum hash proc binding dir io method regexp struct float object_space argf gc env process).each do |lib|
|
21
14
|
require_relative "backports/#{lib}"
|
22
15
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
if RUBY_VERSION < '1.8.7'
|
2
|
+
class << ARGF
|
3
|
+
# Standard in Ruby 1.8.7.
|
4
|
+
make_block_optional :each, :each_line, :each_byte
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
class << ARGF
|
9
|
+
# Standard in Ruby 1.8.7.
|
10
|
+
def bytes
|
11
|
+
to_enum :each_byte
|
12
|
+
end unless method_defined? :bytes
|
13
|
+
|
14
|
+
# Standard in Ruby 1.8.7.
|
15
|
+
def chars
|
16
|
+
to_enum :each_char
|
17
|
+
end unless method_defined? :chars
|
18
|
+
|
19
|
+
# Standard in Ruby 1.8.7.
|
20
|
+
def each_char
|
21
|
+
return to_enum(:each_char) unless block_given?
|
22
|
+
if $KCODE == "UTF-8"
|
23
|
+
lookup = 7.downto(4)
|
24
|
+
while c = read(1) do
|
25
|
+
n = c[0]
|
26
|
+
leftmost_zero_bit = lookup.find{|i| n[i].zero? }
|
27
|
+
case leftmost_zero_bit
|
28
|
+
when 7 # ASCII
|
29
|
+
yield c
|
30
|
+
when 6 # UTF 8 complementary characters
|
31
|
+
next # Encoding error, ignore
|
32
|
+
else
|
33
|
+
more = read(6-leftmost_zero_bit)
|
34
|
+
break unless more
|
35
|
+
yield c+more
|
36
|
+
end
|
37
|
+
end
|
38
|
+
else
|
39
|
+
while s = read(1)
|
40
|
+
yield s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
self
|
45
|
+
end unless method_defined? :each_char
|
46
|
+
|
47
|
+
# Standard in Ruby 1.8.7.
|
48
|
+
alias_method :getbyte, :getc
|
49
|
+
|
50
|
+
# Standard in Ruby 1.8.7.
|
51
|
+
alias_method :readbyte, :readchar
|
52
|
+
|
53
|
+
# Standard in Ruby 1.8.7.
|
54
|
+
def lines(*args)
|
55
|
+
to_enum :each_line, *args
|
56
|
+
end unless method_defined? :lines
|
57
|
+
end
|
data/lib/backports/array.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
class Array
|
2
|
+
# Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
2
3
|
class << self
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
# Try to convert obj into an array, using to_ary method.
|
5
|
+
# Returns converted array or nil if obj cannot be converted
|
6
|
+
# for any reason. This method is to check if an argument is an array.
|
7
|
+
def try_convert(obj)
|
8
|
+
return nil unless obj.respond_to?(:to_ary)
|
9
|
+
Type.coerce_to(obj, Array, :to_ary)
|
10
|
+
end
|
7
11
|
end
|
8
12
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
# Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
13
|
+
|
14
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
13
15
|
def combination(num)
|
14
|
-
num = num
|
16
|
+
num = Type.coerce_to num, Fixnum, :to_int
|
15
17
|
return to_enum(:combination, num) unless block_given?
|
16
18
|
return self unless (0..size).include? num
|
17
19
|
# Implementation note: slightly tricky.
|
@@ -27,32 +29,43 @@ class Array
|
|
27
29
|
picks[move...num] = (new_index...(new_index+num-move)).to_a
|
28
30
|
end
|
29
31
|
end unless method_defined? :combination
|
30
|
-
|
31
|
-
# Standard in Ruby 1.
|
32
|
-
def cycle(
|
33
|
-
return to_enum(:cycle,
|
34
|
-
|
35
|
-
|
32
|
+
|
33
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
34
|
+
def cycle(n = nil, &block)
|
35
|
+
return to_enum(:cycle, n) unless block_given?
|
36
|
+
if n.nil?
|
37
|
+
loop(&block)
|
38
|
+
else
|
39
|
+
n = Type.coerce_to n, Fixnum, :to_int
|
40
|
+
n.times{each(&block)}
|
41
|
+
end
|
42
|
+
nil
|
36
43
|
end unless method_defined? :cycle
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
44
|
+
|
45
|
+
# Standard in rails, and we use it here...
|
46
|
+
def extract_options!
|
47
|
+
last.is_a?(::Hash) ? pop : {}
|
48
|
+
end unless method_defined? :extract_options!
|
49
|
+
|
50
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
51
|
+
make_block_optional :collect!, :map!, :each, :each_index, :reverse_each, :reject, :reject!, :delete_if, :test_on => [42]
|
52
|
+
|
53
|
+
# flatten & flatten!, standard in ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
41
54
|
unless ([[]].flatten(1) rescue false)
|
42
55
|
|
43
56
|
# Recursively flatten any contained Arrays into an one-dimensional result.
|
44
57
|
# Adapted from rubinius'
|
45
|
-
def flatten_with_optional_argument(level
|
46
|
-
return flatten_without_optional_argument unless level || level == (1/0.0)
|
58
|
+
def flatten_with_optional_argument(level=-1)
|
47
59
|
dup.flatten!(level) || self
|
48
60
|
end
|
49
61
|
|
50
62
|
# Flattens self in place as #flatten. If no changes are
|
51
63
|
# made, returns nil, otherwise self.
|
52
64
|
# Adapted from rubinius'
|
53
|
-
def flatten_with_optional_argument!(level
|
54
|
-
|
55
|
-
|
65
|
+
def flatten_with_optional_argument!(level=-1)
|
66
|
+
level = Type.coerce_to(level, Integer, :to_int)
|
67
|
+
return flatten_without_optional_argument! unless level >= 0
|
68
|
+
|
56
69
|
ret, out = nil, []
|
57
70
|
ret = recursively_flatten_finite(self, out, level)
|
58
71
|
replace(out) if ret
|
@@ -82,8 +95,8 @@ class Array
|
|
82
95
|
end
|
83
96
|
private :recursively_flatten_finite
|
84
97
|
end # flatten & flatten!
|
85
|
-
|
86
|
-
# index
|
98
|
+
|
99
|
+
# index. Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
87
100
|
unless ([1].index{true} rescue false)
|
88
101
|
def index_with_block(*arg)
|
89
102
|
return index_without_block(*arg) unless block_given? && arg.empty?
|
@@ -93,27 +106,37 @@ class Array
|
|
93
106
|
alias_method_chain :index, :block
|
94
107
|
alias_method :find_index, :index
|
95
108
|
end
|
96
|
-
|
97
|
-
# pop. Standard in Ruby 1.
|
109
|
+
|
110
|
+
# pop. Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
98
111
|
unless ([1].pop(1) rescue false)
|
99
|
-
def pop_with_optional_argument(
|
100
|
-
return pop_without_optional_argument if
|
101
|
-
n =
|
102
|
-
|
112
|
+
def pop_with_optional_argument(n = Undefined)
|
113
|
+
return pop_without_optional_argument if n == Undefined
|
114
|
+
n = Type.coerce_to(n, Fixnum, :to_int)
|
115
|
+
raise ArgumentError, "negative array size" if n < 0
|
116
|
+
first = size - n
|
117
|
+
first = 0 if first < 0
|
118
|
+
slice!(first..size).to_a
|
103
119
|
end
|
104
120
|
alias_method_chain :pop, :optional_argument
|
105
121
|
end
|
106
|
-
|
122
|
+
|
123
|
+
# Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
107
124
|
def product(*arg)
|
125
|
+
# Implementation notes: We build an enumerator for all the combinations
|
126
|
+
# by building it up successively using "inject" and starting from a trivial enumerator.
|
127
|
+
# It would be easy to have "product" yield to a block but the standard
|
128
|
+
# simply returns an array, so you'll find a simple call to "to_a" at the end.
|
129
|
+
#
|
108
130
|
trivial_enum = Enumerator.new{|yielder| yielder.yield [] }
|
109
|
-
[self, *arg].
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
131
|
+
[self, *arg].map{|x| Type.coerce_to(x, Array, :to_ary)}.
|
132
|
+
inject(trivial_enum) do |enum, array|
|
133
|
+
Enumerator.new do |yielder|
|
134
|
+
enum.each do |partial_product|
|
135
|
+
array.each do |obj|
|
136
|
+
yielder.yield partial_product + [obj]
|
137
|
+
end
|
114
138
|
end
|
115
139
|
end
|
116
|
-
end
|
117
140
|
end.to_a
|
118
141
|
end unless method_defined? :product
|
119
142
|
|
@@ -126,35 +149,45 @@ class Array
|
|
126
149
|
end
|
127
150
|
alias_method_chain :rindex, :block
|
128
151
|
end
|
129
|
-
|
130
|
-
#
|
152
|
+
|
153
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
154
|
+
def sample(n = Undefined)
|
155
|
+
return self[rand(size)] if n == Undefined
|
156
|
+
n = Type.coerce_to(n, Fixnum, :to_int)
|
157
|
+
raise ArgumentError, "negative array size" if n < 0
|
158
|
+
n = size if n > size
|
159
|
+
result = Array.new(self)
|
160
|
+
n.times do |i|
|
161
|
+
r = i + rand(size - i)
|
162
|
+
result[i], result[r] = result[r], result[i]
|
163
|
+
end
|
164
|
+
result[n..size] = []
|
165
|
+
result
|
166
|
+
end unless method_defined? :sample
|
167
|
+
|
168
|
+
# shift. Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
131
169
|
unless ([1].shift(1) rescue false)
|
132
|
-
def shift_with_optional_argument(
|
133
|
-
return shift_without_optional_argument if
|
134
|
-
n =
|
170
|
+
def shift_with_optional_argument(n = Undefined)
|
171
|
+
return shift_without_optional_argument if n == Undefined
|
172
|
+
n = Type.coerce_to(n, Fixnum, :to_int)
|
173
|
+
raise ArgumentError, "negative array size" if n < 0
|
135
174
|
slice!(0, n)
|
136
175
|
end
|
137
176
|
alias_method_chain :shift, :optional_argument
|
138
177
|
end
|
139
|
-
|
140
|
-
|
141
|
-
def sample(*arg)
|
142
|
-
return self[rand(size)] if arg.empty?
|
143
|
-
n = [arg.first.to_i, size].min
|
144
|
-
index = Array.new(size)
|
145
|
-
n.times do |i|
|
146
|
-
r = i + rand(size - i)
|
147
|
-
index[i], index[r] = index[r] || r, index[i] || i
|
148
|
-
end
|
149
|
-
values_at(*index.first(n))
|
150
|
-
end unless method_defined? :sample
|
151
|
-
|
178
|
+
|
179
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
152
180
|
def shuffle
|
153
|
-
|
181
|
+
dup.shuffle!
|
154
182
|
end unless method_defined? :shuffle
|
155
183
|
|
184
|
+
# Standard in Ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
|
156
185
|
def shuffle!
|
157
|
-
|
186
|
+
size.times do |i|
|
187
|
+
r = i + rand(size - i)
|
188
|
+
self[i], self[r] = self[r], self[i]
|
189
|
+
end
|
190
|
+
self
|
158
191
|
end unless method_defined? :shuffle!
|
159
192
|
|
160
193
|
end
|
data/lib/backports/binding.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Binding
|
2
|
-
# Standard in ruby 1.
|
2
|
+
# Standard in ruby 1.8.7+. See official documentation[http://ruby-doc.org/core-1.9/classes/Symbol.html]
|
3
3
|
def eval(expr, *arg)
|
4
4
|
Kernel.eval(expr, self, *arg)
|
5
5
|
end unless method_defined? :eval
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# These are non-standard extensions
|
2
|
+
|
3
|
+
class Module
|
4
|
+
# Metaprogramming utility to make block optional.
|
5
|
+
# Tests first if block is already optional when given options
|
6
|
+
def make_block_optional(*methods)
|
7
|
+
options = methods.extract_options!
|
8
|
+
methods.each do |selector|
|
9
|
+
next unless method_defined? selector
|
10
|
+
unless options.empty?
|
11
|
+
test_on = options[:test_on] || self.new
|
12
|
+
next if (test_on.send(selector, *options.fetch(:arg, [])) rescue false)
|
13
|
+
end
|
14
|
+
|
15
|
+
arity = instance_method(selector).arity
|
16
|
+
last_arg = []
|
17
|
+
if arity < 0
|
18
|
+
last_arg = ["*rest"]
|
19
|
+
arity = -1-arity
|
20
|
+
end
|
21
|
+
arg_sequence = ((0...arity).map{|i| "arg_#{i}"} + last_arg + ["&block"]).join(", ")
|
22
|
+
|
23
|
+
alias_method_chain(selector, :optional_block) do |aliased_target, punctuation|
|
24
|
+
module_eval <<-end_eval
|
25
|
+
def #{aliased_target}_with_optional_block#{punctuation}(#{arg_sequence})
|
26
|
+
return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, #{arg_sequence}) unless block_given?
|
27
|
+
#{aliased_target}_without_optional_block#{punctuation}(#{arg_sequence})
|
28
|
+
end
|
29
|
+
end_eval
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module Type
|
36
|
+
# From Rubinius
|
37
|
+
class << self
|
38
|
+
def coerce_to(obj, cls, meth)
|
39
|
+
return obj if obj.kind_of?(cls)
|
40
|
+
|
41
|
+
begin
|
42
|
+
ret = obj.__send__(meth)
|
43
|
+
rescue Exception => e
|
44
|
+
raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \
|
45
|
+
"(#{e.message})"
|
46
|
+
end
|
47
|
+
raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls
|
48
|
+
ret
|
49
|
+
end unless method_defined? :coerce_to
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.coerce_to_comparison(a, b, cmp = (a <=> b))
|
53
|
+
raise ArgumentError, "comparison of #{a} with #{b} failed" if cmp.nil?
|
54
|
+
return 1 if cmp > 0
|
55
|
+
return -1 if cmp < 0
|
56
|
+
0
|
57
|
+
end unless method_defined? :coerce_to_comparison
|
58
|
+
end
|
59
|
+
|
60
|
+
# From Rubinius
|
61
|
+
Undefined = Object.new unless Kernel.const_defined? :Undefined
|