An elegant way to log with a Ruby block
Imagine you created a generator much like Rails. It creates a series of directories and copy a set of files to a specific location. Some things may fail, and you need a nice way to show what’s going on behind the scenes.
I was browsing some code on GitHub and found an elegant approach to this problem.
module Glue
module Generator
extend self
extend Glue::Helper
def generate!(options={})
templates = File.expand_path(File.dirname(__FILE__) + "/../../templates")
output = File.expand_path(options[:path])
# create root directory
run "creating #{Colorize.yellow(output, :style => :underscore)} directory" do
FileUtils.mkdir_p(output)
end
# create javascripts directory
run %(creating #{Colorize.yellow("public/javascripts")} directory) do
FileUtils.mkdir_p File.join(output, "public/javascripts")
end
# create images directory
run %(creating #{Colorize.yellow("public/images")} directory) do
FileUtils.mkdir_p File.join(output, "public/images")
end
# create views directory
run %(creating #{Colorize.yellow("views/layouts")} directory) do
FileUtils.mkdir_p File.join(output, "views/layouts")
end
end
end
end
module Glue
module Helper
def run(message, &block)
$stdout << "\n#{message}... "
begin
yield
$stdout << Colorize.green("done!")
rescue Exception => e
$stdout << Colorize.red("error ~ #{e.message}")
end
end
end
end
This code does a few interesting things:
- the “run” method is defined inside a helper module. It begins by receiving a message (what are you doing right now?) and a block. It starts by giving control to the caller with a yield (now the execution inside the “run” method is halted). So the block passed to the run method is now executed. This block is actually the lines you see above between “run … / end”;
- So in this block you can “do your thing”. For example, create a directory, request some info from a remote API, or whatever;
- When the block is finished running, the lines after yield (in the “run” method) are executed. If no exception is raised a Ok message is printed, otherwise we’ll see what went wrong with the specific exception message.
This is very cool. You can now execute failure-prone tasks in a very elegant way, and with a really nice syntax
This code was created by Nando Vieira in an interesting project called Glue, which is a simple static site generator for Ruby that uses Haml, Sass and Textile/Markdown. The documentation is here.


