Fork me on GitHub

Friday, April 25, 2008

Ruby: Builder Pattern

Today morning I was reading through the blogs when I found this interesting post from Venkat on Groovy fluency. It is actually a builder pattern for constructing emails. I thought this example to be in╦łtriguing. As I am a ruby guy (Not a geek or a hacker. I am not sure if I am qualified to call myself that :-) ) I thought if I can write this in Ruby.

The problem is to create a mailer class in which you can set from, to, subject and body and send it. The from, to, subject and body needs to be passed through a block to the send method of mailer. Venkat has refactored to a stage where you call the mailer like this.


Mailer.send{
from "Sai"
to "matz"
subject "Ruby"
body "I love ruby"
}


I knew the solution was in using instance_eval. The problem was how to delegate each line of code in the block passed to be executed in the context of the mailer. First I tried to yield inside the instance_eval block. Unfortunately it did not work out. Later I figured out if I pass the block to the instance_eval then it will be possible to execute the block with respect to the mailer instance. So here it goes.
class Mailer
def from(fromAddress)
puts "from : #{fromAddress}"
end
def to(toAddress)
puts "to : #{toAddress}"
end
def subject(theSubject)
puts "subject : #{theSubject}"
end
def body(theBody)
puts "body : #{theBody}"
end
def self.send(&blk)
m = Mailer.new
m.instance_eval(&blk)
puts "sending the mail..."
end
end

Mailer.send{
from "Sai"
to "matz"
subject "Ruby"
body "I love ruby"
}

The pattern used here is builder pattern normally employed to construct complex objects out of different components. Take a look at GOF patterns book or Ruby design patterns for reference.
Usage as far I know are Markaby, XML builder, Shoes GUI toolkit. May be more are out there.
If you know any known usage in Ruby please add it to the comments.

Hope this post was useful as it was for me.

No comments: