Joe Yates' Blog

Programming and DevOps

How to Forward Blocks in Ruby

TL;DR

Use Proc.new

Calling Enumerators – normal use

You’re writing some code which calls an Enumerator – a function that makes repeated calls to the block of code that you provide.

1
2
3
4
5
6
def yield_me_2_things
  yield 'Thing 1'
  yield 'Thing 2'
end

yield_me_2_things { |x| puts x }

This will print:

1
2
Thing 1
Thing 2

The values are supplied by yield_me_2_things and the printing is done in the block, { |x| puts }, that is passed to that method.

Generalize

I can now make a generalized method, to handle any number of things:

1
2
3
4
5
6
7
8
def yield_me_n_things(n)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    yield thing
  end
end

yield_me_n_things(2) { |x| puts x }

…the output is the same.

An alternative: use a block

I could equally have implemented the method using a &block parameter – for the caller, it makes no difference:

1
2
3
4
5
6
7
8
def call_this_block_with_n_things(n, &block)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

call_this_block_with_n_things(2) { |x| puts x }

…the output is the same.

The problem

What if I want one Enumerator to call another?

What if I want to keep the specific version (yield_me_2_things) but just make it call the generalized method?

1
2
3
4
5
6
7
8
9
10
11
12
13
def enumerate_n_things(n) # How do I receive the block?
  1.upto(n) do |i|
    thing = "Thing #{i}"
    # How do I call the block?
  end
end

def enumerate_2_things
  enumerate_n_things(2) # How do I forward the block?
end

enumerate_2_things { |x| puts x }
enumerate_2_things(2) { |x| puts x }

How should I write the two methods, while keeping both usable indipendently?

Attempt 1: Forward using yield

With yield, you don’t explicitly receive the block, you just call it. Does that work across two levels? I.e., does the block get passed to method I call?

1
2
3
4
5
6
7
8
9
10
11
12
def enumerate_n_things(n)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    yield thing
  end
end

def enumerate_2_things
  enumerate_n_things(2)
end

enumerate_2_things { |x| puts x }

No, doesn’t work, enumerate_n_things doesn’t receive a block.

I get this error:

1
no block given (yield) (LocalJumpError)

Attempt 2: Forward using a block

1
2
3
4
5
6
7
8
9
10
11
12
def enumerate_n_things(n, block) # Note: no '&'
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

def enumerate_2_things(&block)
  enumerate_n_things(2, block)
end

enumerate_2_things { |x| puts x }

Prints:

1
2
Thing 1
Thing 2

But we can no longer pass a block to the generalized method:

1
enumerate_n_things(2) { |x| puts x }

enumerate_n_things now expects the block as a normal parameter.

I get this error:

1
wrong number of arguments (1 for 2)

Solution: Proc.new

1
2
3
4
5
6
7
8
9
10
11
12
13
def enumerate_n_things(n, block = Proc.new)
  1.upto(n) do |i|
    thing = "Thing #{i}"
    block.call thing
  end
end

def enumerate_2_things(proc = Proc.new)
  enumerate_n_things(2, block)
end

enumerate_2_things { |x| puts x }
enumerate_n_things(2) { |x| puts x }

Both calls now work!

Proc.new transforms any block passed to a method into a Proc. If we use that as the default value for a block parameter we can call methods directly with blocks, or forward blocks between enumerators.

Instant Sinatra Starter

I was asked to write a book about Sinatra, to be published by Packt Publishing.

Instant Sinatra Starter

The book is called “Instant Sinatra Starter” and is part of Packtpub’s Instant series.

Although the book is very short – the final version is 48 pages – it took about six months from initial planning to publication.

My target audience is people who have a little programming experience, so it doesn’t aim to teach you programming in general, or Ruby specifically.

The main section of the book follows the steps you need to develop an address book application.

The topics covered are:

  • Sinatra setup,
  • Templating (using Slim),
  • Getting an app online using Heroku,
  • GET and POST requests,
  • Integration testing,
  • Database access.

The code from the book is available on GitHub.

My Everyday Find Command

When I’m searching for files, I use this function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# f - everyday find
# usage:
#   f filename_fragment [path]
# skips whatever you list in _exclude_matches
_exclude_matches=(bundle .git *.pyc)
_excludes=''
for _match in $_exclude_matches; do
  _excludes="${_excludes}-name '$_match' -prune -o "
done

eval "
function my_everyday_find() {
  find \$2 \
    $_excludes \
    -name \"*\$1*\"    \
    -print;
}
"
unset _exclude_matches _excludes _match
alias f=my_everyday_find

It searches for files and directories with partial matches of the first parameter:

1
2
$ f 26
./db/migrate/20121003094826_add_foo_to_bar.rb

If I supply a second parameter, it is taken as the directory to search in:

1
2
3
$ f 26 ..
../api/db/migrate/20121003094826_add_foo_to_bar.rb
../redmine/db/migrate/20091017212644_add_missing_indexes_to_messages.rb

Ruby Bareword Assignment and Method Calls With Implicit Self

Problem

If I do this:

Problem - problem.rb
1
2
puts foo
foo = 3

there is always the doubt whether I’m accessing a local variable, or calling methods foo and foo=.

TL;DR

When you want to call an instance’s own methods, use self:

TL;DR - tldr.rb
1
2
self.foo             # Calls foo
self.foo = 'bar'     # Calls foo=

HTML History API

The HTML5 history API allows AJAX-based sites to avoid “breaking the back button”. Every time you update the page, you store the new content is the window.history object. When the user presses the back button, you retrieve the current item from window.history and update the page with it.

Overriding the Insertion Operator for C++ Template Classes

Dump an Active Record object to Standard Out - dump_active_record_object.cpp
1
2
Person person( 123 );
std::cout << person << endl;

While working on my C++ ActiveRecord implementation, I had a few problems implementing the insertion operator for the main ActiveRecord::Base class.

The class ActiveRecord::Base class is a template class, and the problem was how to correctly declare the operator.

At the time I was unable to find examples on the Internet, so I thought I’d provide my own.

Rake::Builder

Use Rake::Builder as a Make Replacement - build.sh
1
$ rake build

I’ve put together a rake-based system for building C and C++ projects.

I’ve called it Rake::Builder, it’s available on GitHub here.

Sinatra: A Real Site

The Site

I have a young relative who draws a lot of comic strips, and thinking it would be nice if he could publish them, I looked around for an Open Source system.
I wanted something that was as near to XKCD as possible - latest comic, next/previous and random.
Not finding anything that was both pretty and ultra-simple, I decided to write my own.
The version for my relative is here - the system will be up on GitHub as soon as I finish making it configurable.