Recently, I created a rake task to load dummy data into a Rails app. I wanted the data to be somewhat random to make it easier to spot design issues depending on data being filled in or left blank. But at the same time, I want to keep my code as readable as possible.
If I wanted a certain field to be filled in for one in five instances, I thought it would be quite readable to have code like this
with_probability '4 in 5' do person.source = ['Walk in', 'Event', 'Word fo mouth', 'Website'].sample end
All I needed to do was write a simple method leveraging Ruby’s block concept:
def with_probability(string, &block) string =~ /^(\d+) in (\d+)$/ probability = $1.to_i total = $2.to_i result = rand(total) < probability if block_given? yield if result else result end end
Simple enough: we pick a random number, and if it fits our criteria, we execute the block. You’ll notice I actually test for the block, because I also wanted to be able to use the method without a block:
person.source = 'Phone call' if with_probability '1 in 3'