Nov
05
Blocks are to Ruby…
What ‘ba’ is to bash.
Without blocks, ruby would be sh…
Say I need to verify a user is old enough to perform a certain action or run a specific method. I could do:
if user.old_enough?(13) user.must_be_13_method else puts "User is not old enough" # where puts is most likely a logger or flash[:error] return false end
However, it quickly becomes tedious to have if/else statements like this all over the place. Wouldn’t it be nice if you could put that error message somewhere else?
Good news. You can!
You can use a block in the old_enough? method of the User class:
def old_enough?(age_in_years, &block) # &block specifies that I plan to send a block
if Time.parse(born_on) < Time.today-age_in_years.years
# block.call executes the block.
# It's the same as yield, except I can pass parameters or call it multiple times.
block.call(self)
else
puts "Sorry. You must be #{age_in_years} years old."
end
end
Then you can do this:
user.old_enough?(13) do |user| user.must_be_13_action end
Here’s a script you can use and run to test this out.
#!/usr/bin/env ruby
require 'rubygems'
require 'active_support'
class User
attr_accessor :born_on
def initialize(attributes = {})
self.born_on = attributes[:born_on]
end
def old_enough?(age_in_years, &block)
if Time.parse(born_on) < Time.today-age_in_years.years
block.call(self)
else
puts "Isn't it past your bedtime?"
end
end
def must_be_13_action
puts "Teenie Boppers Welcome"
end
end
user = User.new(:born_on => '1992-01-01')
user.old_enough?(13) do |user|
user.must_be_13_action
end
user.old_enough?(18) do |user|
user.must_be_18_action
end
Because I am initializing the user with a birthdate in 1992 (between the ages of 13 and 18 as of this entry’s publish date), the output will be:
Teenie Boppers Welcome Isn't it past your bedtime?
No Comments