aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2010-06-05 01:13:37 +0200
committerXavier Noria <fxn@hashref.com>2010-06-05 01:15:17 +0200
commit67a43554f153a3ddb97039b5fac305c0619dd372 (patch)
treedefe65bc4dec8844525c93a348dfc9a97eacf237 /activesupport
parent6401ab587021b78c3dc5e4a5ac831823a9258481 (diff)
downloadrails-67a43554f153a3ddb97039b5fac305c0619dd372.tar.gz
rails-67a43554f153a3ddb97039b5fac305c0619dd372.tar.bz2
rails-67a43554f153a3ddb97039b5fac305c0619dd372.zip
removes Array#random_element and backports Array#sample from Ruby 1.9, thanks to Marc-Andre Lafortune
Diffstat (limited to 'activesupport')
-rw-r--r--activesupport/CHANGELOG2
-rw-r--r--activesupport/lib/active_support/core_ext/array/random_access.rb22
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb30
3 files changed, 42 insertions, 12 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index d853788e00..0e24cc138a 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -4,7 +4,7 @@
* Ruby 1.9: support UTF-8 case folding. #4595 [Norman Clarke]
-* Renames Array#rand -> Array#random_element. [Santiago Pastorino, Rizwan Reza]
+* Removes Array#rand and backports Array#sample from Ruby 1.9, thanks to Marc-Andre Lafortune. [fxn]
* Ruby 1.9: Renames last_(month|year) to prev_(month|year) in Date and Time. [fxn]
diff --git a/activesupport/lib/active_support/core_ext/array/random_access.rb b/activesupport/lib/active_support/core_ext/array/random_access.rb
index 67c322daea..7a4836cecd 100644
--- a/activesupport/lib/active_support/core_ext/array/random_access.rb
+++ b/activesupport/lib/active_support/core_ext/array/random_access.rb
@@ -1,6 +1,20 @@
class Array
- # Returns a random element from the array.
- def random_element
- self[Kernel.rand(length)]
- end
+ # Backport of Array#sample based on Marc-Andre Lafortune's http://github.com/marcandre/backports/
+ def sample(n=nil)
+ return self[Kernel.rand(size)] if n.nil?
+ n = n.to_int
+ rescue Exception => e
+ raise TypeError, "Coercion error: #{n.inspect}.to_int => Integer failed:\n(#{e.message})"
+ else
+ raise TypeError, "Coercion error: obj.to_int did NOT return an Integer (was #{n.class})" unless n.kind_of? Integer
+ raise ArgumentError, "negative array size" if n < 0
+ n = size if n > size
+ result = Array.new(self)
+ n.times do |i|
+ r = i + Kernel.rand(size - i)
+ result[i], result[r] = result[r], result[i]
+ end
+ result[n..size] = []
+ result
+ end unless method_defined? :sample
end \ No newline at end of file
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 1f7cdb8ec1..54376deee5 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -359,14 +359,30 @@ class ArrayUniqByTests < Test::Unit::TestCase
end
class ArrayExtRandomTests < ActiveSupport::TestCase
- def test_random_element_from_array
- assert_nil [].random_element
-
- Kernel.expects(:rand).with(1).returns(0)
- assert_equal 'x', ['x'].random_element
+ def test_sample_from_array
+ assert_nil [].sample
+ assert_equal [], [].sample(5)
+ assert_equal 42, [42].sample
+ assert_equal [42], [42].sample(5)
+
+ a = [:foo, :bar, 42]
+ s = a.sample(2)
+ assert_equal 2, s.size
+ assert_equal 1, (a-s).size
+ assert_equal [], a-(0..20).sum{a.sample(2)}
+
+ o = Object.new
+ def o.to_int; 1; end
+ assert_equal [0], [0].sample(o)
+
+ o = Object.new
+ assert_raises(TypeError) { [0].sample(o) }
+
+ o = Object.new
+ def o.to_int; ''; end
+ assert_raises(TypeError) { [0].sample(o) }
- Kernel.expects(:rand).with(3).returns(1)
- assert_equal 2, [1, 2, 3].random_element
+ assert_raises(ArgumentError) { [0].sample(-7) }
end
end