Skip to content
Create complex function callbacks with ease!
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Make callbacks easily and build blocks with ease! BlockBuilder is intended to be used with more heavy weight method calls that might require intermediate callbacks. It's almost like creating classes on the fly!


Add to your Gemfile:

gem "blockbuilder", "~> 0.0.1"

And require BlockBuilder in your application:

require 'block_builder'


BlockBuilder makes use of the instance_eval method. As such, using self may not work as you expect. In addition, you may not be able to access some variables outside the scope of the block.

File Download Example

Downloading a file probably doesn't merit the block builder, but it demonstrates the concept of callbacks.

def download_file(url, &block)
  # Configure your block here, along with defaults
  builder = block do
    # Set optional default variables!
    set :verbose, true
    on_fail do |http_code, body|
      puts "Oh no! HTTP download failed! Code: #{http_code}"
      puts "Downloaded body: #{body}" if verbose
    on_success do |body|
      puts "Downloaded file Successfully!"
  # Now execute your blocks! Note you don't have to explicitly
  # define any of your callbacks.
  result = download_some_file_from_internet(url)
  if result.http_code == 200 result.body
  else result.http_code, result.body

# Now you can call the method above and change the defaults!
download_file "" do
  on_success do |body|'some/file.txt', 'w') {|f| f.write body }

# Only outputs "Oh no! HTTP download failed! Code: 404"
download_file "" do
  set :verbose, false

Callbacks and Remote Data

Sometimes you might connect to another service or API that contains critical information. And perhaps you need to query multiple times with this API to get the data you need. Callbacks can help with this!

# As a convention, you should always document a block builder method and let consumers of
# this method know how to use it!
# @example
#   # Here is a code sample on how to use this method, etc
def create_remote_user(username, password, &block)
  builder = block do
    set :logger,
    # You can force the creation of a callback using the abstract operator. By default,
    # without the abstract modifier, calling an undefined callback will simply do nothing
    abstract :on_user_created
  # If any callbacks label as 'abstract' aren't defined, then code execution will
  # never reach this line.
  # Here, you may first want to create the user and create a callback. This callback
  # can then be used to quickly save an entry in the database before other operations
  # are executed. This is useful, for example, if the server crashes during the middle
  # of the request or there is a bug later in the method call. This way, at least you
  # have the user information saved in your local database and you can retrieve the
  # user information later.
  result = api.create_user username, password

  # Now we can keep on executing methods and have somewhere else take care of it. Using
  # the set logger variable, we can allow someone to externally change the logger used.
  # Now what if the connection timed out here? Or the server crashed? That's the point
  # of the earlier callback! It allows you to save partial data without interfering
  # with the internal logic of this method!
  start =
  result2 = api.some_very_time_intensive_call_involving(username) "Executed time intensive call in #{ - start} sec!"
  # Another fun use for this: collecting statistics! It might be useful to collect a
  # bunch of statistics for a particular task. However, not every consumer of your
  # method will care for statistics. Just for fun, let's only calculate some
  # statistics about this method call only if they care to calculate stats!
  # We use 'builder.defined?' here because doing
  # will compile statistics, regardless of whether 'generate_statistics' is defined.
  if builder.defined? :generate_statistics
    stats = some_lengthy_statistic_compilation
  # Now you can add any more callbacks as you see fit! And don't forget, you can still
  # return some data from this method call if you want!

Now you can use this method in multiple places. Here, assume this is where the code is primarily used:

create_remote_user 'user', 'password' do
  # This easily lets us use our Rails logger
  set :logger, Rails.logger
  # Remember, our abstract callback was declared, so we must define it here. In this
  # case, assume we have a Ruby on Rails model that deals with saving saved data
  on_user_created do |result|
    u =

Finally, assume this is some benchmark suite, or something else:

# Assume this is some benchmark suite or testing file
create_remote_user 'user', 'password' do
  on_user_created do |result|
    # .. Implement here
  # In this case, we might enjoy statistics
  generate_statistics do |stats|
    puts "Statistics for this operation:"
    puts " * Total execution time: #{stats.exec_time}"
    puts "..."


Add this line to your application's Gemfile:

gem 'blockbuilder'

And then execute:

$ bundle

Or install it yourself as:

$ gem install blockbuilder
You can’t perform that action at this time.