I wanted to get a sample from 1 to 10, when I was writing a test case. So as a believer in ruby magic, I just did .sample
on Range 1..10
. It did not work! I got this
2.5.7 :005 > (1..10).sample
Traceback (most recent call last):
1: from (irb):5
NoMethodError (undefined method `sample' for 1..10:Range)
Okay, cool! Maybe there is a random method. So I called .random on the Range. Nope, that did not work either
2.5.7 :004 > (1..10).random
Traceback (most recent call last):
1: from (irb):4
NoMethodError (undefined method `random' for 1..10:Range)
What, are you serious? This should have been there right? Well, turns out the only way to get this working is by doing rand(1..10)
. But this is not very object-oriented, is it? So how can we make this object-oriented?
Enter Open Classes, In ruby .. you can open whatever the class the language provides and put your own methods in it, as long as you are not breaking the language
class Range
def sample
rand(self)
end
end
Now things work as expected
2.5.7 :011 > (1..10).sample
=> 5
Explanation:
What did I just do there in the above example?
I opened Range
class, declared an instance method called sample
. Inside it, I am calling rand
with self as an argument. When you use (1..10)
it's just a syntactic sugar of the representation Range.new(1,10)
. So basically (1..10)
is an instance of the Range
class. Hence by defining an instance method sample
, I made it available to be called on our object (1..10)
.
Hope, this cleared things up. Happy programming :)
Top comments (2)
Nice explanation
Awesome; I didn't know that the
rand
function could optionally take a range! Thanks for sharing this.