MultiBlock is a mini framework for passing multiple blocks to methods. It uses “named procs” to accomplish this in a nice way. The receiving method can either yield all blocks, or just call specific ones, identified by order or name.
These gem was build during a codebrawl contest. You might also take a look at the other entries: codebrawl.com/contests/methods-taking-multiple-blocks
gem install multi_block
A named proc acts like a normal proc, but has got a name attribute. You can create it by calling a method with the desired name on proc
:
>> a = proc.even?{ |e| e.even? } => #<NamedProc:0x00000001ffc340@(irb):1> >> a.name => :even? >> a[42] => false
In the same way, you can create lambdas:
>> b = lambda.doubler{ |e| e * 2 } => #<NamedProc:0x000000020685e0@(irb):7 (lambda)> >> b.name => :doubler >> b[21] => 42 >> b.lambda? => true
The first argument given to yield always defines the desired block(s). The other arguments get directly passed to the block(s). So these are example calls to the block:
yield # calls all given procs without args yield :success # calls :success proc without args yield :success, "Code Brawl!" # calls :success proc with message yield 1 # calls first proc (:success in this case) yield [:success, :bonus] # calls :success and :bonus without args yield [:success, :bonus], "Code Brawl!" # calls both procs with same arg yield success: "Code Brawl!", # calls each keyed proc, error: [500, "Internal Brawl Error"] # values are the args
Consider these two example methods:
def ajax yield rand(6) != 0 ? :success : :error # calls the :success block if everything worked well end def dice random_number = rand(6) yield random_number, random_number + 1 # calls the n-th block end
It’s done by calling the blocks
helper method:
ajax &blocks[ proc.success do puts "Yeah!" end, proc.error do puts "Error..." end, ]
The dice method could, for example, be called in this way:
dice &blocks[ proc{ ":(" }, proc{ ":/" }, proc{ ":O" }, proc{ ":b" }, proc{ ":P" }, proc{ rand(42) != 0 ? ":)" : ":D"}, ]
If you like the slim &to_proc
operator, you can further optimize the syntax by calling:
Array.send :include, MultiBlock::Array
Now, it’s getting real hot:
do_something, some_argument, &[ proc.easy_way do # do it the easy way end, proc.complex_way do # use complex heuristics, etc. end, ]
Excellent