Blog

Nov
05
Blocks are to Ruby…
by ELC | Article

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