Methods taking multiple blocks

Ruby makes it trivial to pass a block of code into our method calls. But what do we do when a method needs two blocks of code or more? For example, a method might want some code to run if an action succeeds and different code to run if it fails.

What would it look like to pass multiple blocks in? How would the method access the blocks it wants for each task? Do we need to worry about making sure passing too many or unexpected blocks are errors?

Let’s make use of Ruby’s ability to modify itself as needed to address this problem. Code up some system for the above that’s superior to passing a Hash full of Proc objects. Throw that code in a Gist and send it in as a solution.

Prize

This week’s winner will receive a copy of James’ Best of Ruby Quiz, a collection of highlights from the first year of Ruby Quiz challenges, sponsored by the Pragmatic Programmers.

This contest is finished

Congratulations to this week's winners! The entries and the contestant names are shown below.

  • .gitignore
    *.sw?
    
    README.md

    (STOP: If you don't want to read about the development process, you can jump directly to the part that says "SwitchBlock".)

    My thoughts on passing multiple blocks

    I had my coming of age as programmer when I learned Scheme (to teach it, some months later, to starry-eyed freshmen). Looking at problems from a functional perspective has colored my vision for some years now, so when I saw the challenge - "make a method that can take two blocks or more" - I immediately knew which magic technique I would have to take from the wizard book: Currying.

    Currying (or if you are German: Schönfinkeln) is a method of "transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument" (Wikipedia). How about an example?

    Let's say you have a method that takes two arguments, like addition. You want to do a + b and you know that your "a" will be five, but the second argument may depend on user input. What do you do? Well, you could save your first argument in a variable, but that's bland stuff for Java programmers. Let's spice it up and use currying.

    What currying a function does is this: It takes your two-argument method and returns a method that takes just one argument. Sounds great, but where did the second argument go? Here is the brilliant part: The curried method will itself return a method! And this method also takes one argument - the "b" one we were missing - and then returns the same as the original function would have if you had not curried it.

    You probably have not returned to many functions from your methods in your daily life, but as you are all Ruby cool cats you know how such a "returned function" will look like: It's a Proc! Rhymes with block, and it is essentially the same thing. So let's just write a method that block-curries other methods.

    So how can we do this? Turns out you can't. Let's look at some ways of passing blocks.

    Passing several blocks in their Proc variety to a function is trival. Just use them like normal arguments:

    first_proc = lamdba {"Yes!!"}
    second_proc = lamdba {"NO!!!!"}
    
    def success_or_failure(condition, first_proc, second_proc)
      if condition
        first_proc.call
      else
        second_proc.call
      end
    end
    
    success_or_failure(true, first_proc, second_proc)
    ==> "Yes!!"
    

    This is easy, but does not look too nice. You have to define the Procs beforehand, or in-place in the method call. The first one sucks because we do not want to use these two procs ever again, so why should we name them? The second one sucks because it looks strange and we already have a nice syntax for passing blocks of code (do/end, or { and }). I tried to get it to execute this:

    blockify :success_or_failure, 2
    
    success_or_failure(true){"Yes!!"}{"NO!!!!"}
    

    Looks easy! If you want several blocks, just write several! But how should you access them from your method? Here is where I wanted to use currying to wrap the original method to make it accept a given number of blocks, make them into Procs and use them as the last arguments. The modified method would first take one block and return a method that again takes one. As you can probably tell, this is the part where it gets hairy.

    I started programming, figuring out what instanceeval, classeval and binding actually do, but I found a problem I could not get past: You can not use the block passing syntax on Proc objects.

    If you have a Proc object, you can call it by using the #call method or its alias, #[]. Examples:

    adder_proc = lambda{|x| x + 1}
    
    adder_proc.call(1) 
    ==> 2
    
    adder_proc[1]
    ==> 2
    

    If you want to make this Proc take a block, you can not just use do/end as you are used to. Actually, you can not do anything except passing the block as a Proc object itself, in a regular argument slot. I don't think there is any way to pgrogram around this and I am now convinced that the syntax I hoped to implement is impossible to achieve. I would love to be wrong, though.

    Less magic, but it works

    After being disappointed that my favorite syntax would never work, I thought about the alternatives. I now knew that you could not just pass multiple blocks using Ruby's normal syntax. So how about wrapping several subblocks in a larger block, giving them a name while doing so:

    success_or_failure(true) {
      success => {"Yes!!"}
      failure => {"NO!!!!"}
    }
    

    Does not look to bad! It is invalid syntax, though. See the "Yes" and "No" that look like blocks? Well, they aren't, they are more like Hashes with a bad syntax. How about this:

    success_or_failure(true) {
      {:success => lambda {"Yes!!"},
       :failure => lambda {"NO!!!!"}}
    }
    

    Now it's a proper Hash of Procs, but it does not look that nice anymore. Anyway, you could now re-write our first method like this, and it would work:

    def success_or_failure(condition)
      if condition?
        yield[:success].call
      else
        yield[:failure].call
      end
    end
    

    The call to yield will give us the block, which is just a hash that let's us select which Proc we want. This would work, but it's ugly. Using #call seems superflous, as yielding should call our block already. Of course, we actually call two blocks - the outer block with yield, the subblock with #call. We need some sweet syntactic sugar to make this go down a bit easier.

    def success_or_failure(condition)
      if condition?
        yield it_to "success"
      else
        yield it_to "failure"
      end
    end
    
    success_or_failure(true){|s|
      s.success {"Yes!!"}
      s.failure {"NO!!!!"}
    }
    

    I think we have something here! This DSL (if you want to call it that) looks nice and is easy to extend to any amount of subblocks. This is what I actually implemented and documented below. I also added some methods that will make it easier for you to implement default behaviour and ensure that a subblock that should get called is actually being passed. Also, you can pass any arguments you want to"yield it_to" and they will be forwarded to your subblock.

    There is no real black magic here: #itto will build a BlockSwitcher object that remembers the name of the subblock it should execute and forwards any arguments you give. It then uses methodmissing to figure out when to actually execute a subblock. Look at the code, it is only 50 lines and easy to understand. You might also want to take a look at the examples.rb file.

    Some last words: You may think "hey, I have seen this before!". I thought so too! While I did not think of it while writing this module, Rails' respond_to and the form helpers use a similar technique. I don't know how they are implemented in Rails, but it is probably not too different. You may want to take a look at that, too.

    Anyways, here's the real README

    SwitchBlock - A way to pass multiple blocks to a method

    Switchblock is a module mixin that adds a simple way to pass multiple blocks to methods to your classes. It does this by creating an object that acts as a switch block.

    Usage

    First, you must include SwitchBlock in your class (or your program). You can now write methods that take multiple blocks using the "it_to" method like this:

    def did_we_succeed?(success)
      if success
        yield it_to "success"
      else
        yield it_to "failure"
      end
    end
    
    did_we_succeed?(true) do |s|
      s.success {"Yes!!"}
      s.failure {"Aw... Bummer..."}
    end
    
    => "Yes!!"
    

    The call to it_to will give you BlockSwitcher, which will take care of the block you give to the method and execute just the subblock(s) you want.

    Features

    As seen in the usage example, you can pass an unlimited number of subblocks to your BlockSwitcher. These will be executed if the method you call on the BlockSwitcher matches whatever name you specified in the "yield it_to" call.

    Switches

    Switches are really simple, just make up a name and use it to call one your subblocks by yielding to it in your "yield itto" call. The first argument to "itto" is the name of the block you want to call. You can use anything that has a #to_sym method.

    def yield_name(name)
      yield it_to name
    end
    
    yield_name("Larry") do |s|
      s.larry {"Hi, Larry!}
    end
    
    => "Hi, Larry!"
    

    Instead of blocks, you can also use a proc as the argument to a switch.

    larry_greeter = lambda {"Hi, Larry"}
    
    yield_name("Larry") do |s|
      s.larry larry_greeter
    end
    
    => "Hi, Larry!"
    

    Any additional arguments you yield after the switch name will be passed on to your subblock.

    def even_or_odd(x)
      if x.even?
        yield it_to "even", x
      else
        yield it_to "odd", x
      end
    end
    
    even_or_odd(5) do |s|
      s.even {|x| "#{x} is an even number" }
      s.odd {|x| "#{x} is an odd number" }
    end
    
    => "5 is an odd number"
    

    The return value of your "yield it_to" call will be the return value of the last executed subblock. If nothing at all is executed, the whole block will return nil. It will raise an error if you use "ensure" (see below).

    Special Switches

    You can use any name for your switch, but "else", "always" and "ensure" have a special meaning and are treated differently.

    always

    You can use "always" as often as you wish, just as normal switches, and it will always execute no matter what.

    else

    You should use "else" only as the last switch of your switchblock. The block you give to it will only execute if no previous block executed before. You can use this to implement default behaviour.

    ensure

    You should use "ensure" only as as the last switch of your switchblock. It will ignore all passed blocks and arguments. It makes sure that at least one of your switches was called during execution and will raise a NothingExecutedError otherwise.

    You can use this to protect against typos. For example, you mistype and write "yield it_to 'succes'" and you have no idea why the block passed to "s.success" in your switchblock is not executed. Using ensure will give you a nice error message in this case, telling you what should have been executed and what was actually present.

    Needless to say, you should probably not use "ensure" together with "always" or "else". You can though, if you are really clever (or just feel like it).

    Notes

    It uses BlankSlate (https://github.com/masover/blankslate) instead of BasicObject because using BasicObject as a superclass breaks error handling. Also, BlankSlate works with 1.8

    The method that generates the BlockSwitcher object is called "it_to" instead of to mainly because Sinatra already has a "to" helper method.

    examples.rb
    #encoding: utf-8
    require "./multiblock.rb"
    include SwitchBlock
    
    def even_or_odd(x)
      if x.even?
        yield it_to "even", x
      else
        yield it_to "odd", x + 1
      end 
    end
    
    res = even_or_odd(4) do |s|
      s.even {|x| puts "I got #{x}, which was even already"; x}
      s.odd {|x| puts "I got #{x}, which was odd"; x} 
      s.always{|x| puts "nice, isn't it?"; x + 2} 
    end
    
    def fizzbuzz(x)
      yield it_to "Fizz" if x % 3 == 0
      yield it_to "Buzz" if x % 5 == 0
      yield it_to "num", x if x % 3 != 0 and x % 5 != 0
      print "\n"
    end
    
    (1..100).each do |x|
      fizzbuzz(x) do |s|
        s.fizz {print "Fizz"}
        s.buzz {print "Buzz"}
        s.num {|x| print x}
      end
    end
    
    def this_works
      puts "This should be success"
      yield it_to "success"
    end
    
    def this_works_not
      puts "This just won't work"
      yield it_to "failure"
    end
    
    def this_does_something_we_did_not_expect
      puts "This has a result that is not handled"
      yield it_to "wtf"
    end
    
    
    block = lambda do |s|
      s.success { puts "-- We did it! ヤッタ!!"}
      s.failure { puts "-- We failed! 桜散る。。。"}
      s.else { puts "-- What is this I don't even"}
    end 
    
    this_works(&block)
    this_works_not(&block)
    this_does_something_we_did_not_expect(&block)
    
    success_block = lambda {puts "Using a lambda or proc in your block also works!"}
    
    this_works do |s|
      s.success success_block
    end
    
    # Using the ensure-switch
    def this_will_break
      yield it_to "succes" # <-- typo
    end
    
    begin
      this_will_break do |s|
        s.success success_block
        s.ensure
      end
    rescue => e
      puts e
    end
    
    multiblock.rb
    #encoding: utf-8
    require "pry"
    require "blankslate"
    
    module SwitchBlock 
    
      class NothingExecutedError < Exception; end
    
      class BlockSwitcher < BlankSlate
        
        def initialize(x, args)
          @x = x
          @args = args
          @ret = nil
          @called = false
          @callees = []
        end
    
        def ensure
          raise NothingExecutedError, "Nothing got executed! Expected one of #{@callees.inspect}, but only got #{@x}" if not @called
        end
        
        def method_missing(method,*args, &block)
          if (method.downcase == @x.to_sym.downcase or method == :always) or (@called == false and method == :else) then
            @called = true
            if args.size > 0 then
              @ret = args.first.call(*@args)
            else
              @ret = block.call(*@args)
            end
          end
          # For error reporting
          @callees << method
          @callees.uniq!
          # Always return something meaningful
          @ret
        end
      end
    
      private
      def it_to(x, *args)
        BlockSwitcher.new(x, args)   
      end
    end
    
    switchblock_spec.rb
    require "./multiblock.rb"
    require "pry"
    
    describe SwitchBlock do
    
      include SwitchBlock
    
      def switch_helper(name, *args)
        yield it_to name, *args    
      end
      
      let(:yes_no_block) {
        lambda do |s|
          s.success {"yes"}
          s.failure {"no"}
        end
      }
    
      let(:ensured_block) {
        lambda do |s|
          s.success {"yes"}
          s.failure {"no"}
          s.ensure
        end
      }
    
      let(:block_with_default) {
        lambda do |s|
          s.success {"yes"}
          s.failure {"no"}
          s.always {"ok"}
        end
      }
    
      let(:block_with_else) {
        lambda do |s|
          s.success {"yes"}
          s.failure {"no"}
          s.else {"maybe"}
        end
      }
    
      it "should be able to switch between codeblocks" do
    
        res = switch_helper("success", &yes_no_block) 
        res.should == "yes"
    
        res = switch_helper("failure", &yes_no_block)
        res.should == "no"
    
      end
    
      it "should return nil if no codeblock is run" do
        res = switch_helper("N/A", &yes_no_block)
        res.should be_nil
      end
    
      it "should also take procs as subblocks" do
    
        procblock = lambda{"procblock"}
    
        res = switch_helper("procblock") do |s|
          s.procblock procblock
        end
    
        res.should == "procblock"
    
      end
    
      it "should execute 'always' switches" do
        res = switch_helper("N/A", &block_with_default)
        res.should == "ok"
      end
    
      it "should return the last evaluated subblock" do
        res = switch_helper("success", &block_with_default)
        res.should == "ok"
      end
    
      it "should raise an error if ensure is used and no code has run" do
        lambda{ switch_helper("suxess", &ensured_block)}.should raise_error
      end
    
      it "should not raise an error if ensure is used and code has run" do
        lambda{ switch_helper("success", &ensured_block)}.should_not raise_error
      end
    
      it "should execute else blocks if nothing else has run" do
        res = switch_helper("N/A", &block_with_else)    
        res.should == "maybe"
      end
    
      it "should not execute else blocks if something else has run" do
        res = switch_helper("failure", &block_with_else)    
        res.should == "no"
      end
    
    end
    
    .rspec
    -f d -c
    
    View full entry
    Finished in 1st place with a final score of 3.6/5. (View the Gist)
  • README.md

    Ruby Methods with Multiple Blocks

    Ruby blocks rock. They're so great, sometimes we want to pass multiple blocks to a method, but, Ruby doesn't allow this. Consider the classic example where we want to perform a block of code if an action succeeds and perform different code if an action fails.

    Fortunately, Ruby provides us the ability to modify itself. So with a couple lines of code we can achieve the above situation. In this case, let's add a perform method to the Proc class. This method will simply yield an anonymous Class with methods defined to handle our blocks.

    class Proc
      def perform(callable)
        self === Class.new do
          method_name = callable.to_sym
          define_method(method_name) { |&block| block.nil? ? true : block.call }
          define_method("#{method_name}?") { true }
          def method_missing(method_name, *args, &block) false; end
        end.new
      end
    end
    

    That's it!

    Example Usage:

    Let’s try it with something useful. Let’s say we’re writing something which needs to happen in an all-or-nothing, atomic fashion. Either the whole thing works, or none of it does. A simple case is tweeting:

    def tweet(message, &block)
      if Twitter.update(message)
        block.perform :success
      else
        block.perform :failure
      end
    end
    

    We call perform on the block and give it a name. Any name will work :success, :error, :fail!, etc. Now we can provide a status if the tweet was successful or not.

    tweet "Ruby methods with multiple blocks. #lolruby" do |on|
      on.success do
        puts "Tweet successful!"
      end
      on.failure do
        puts "Sorry, something went wrong."
      end
    end
    

    Output:

    Tweet successful!
    

    The nice thing here is that we can define our own DSL. We don't need to worry about making sure passing too many or unexpected blocks. We could have easily said where.success or on.error or update.fail!.

    Bonus: In addition to wrapping code in blocks, our Proc#perform method defines boolean style methods. So we could have call the tweet method like this if we wanted to:

    tweet "Ruby methods with multiple blocks. #lolruby" do |update|
      puts "Tweet successful!" if update.success?
      puts "Sorry, something went wrong." if update.failure?
    end
    
    proc_test.rb
    require 'minitest/autorun'
    require File.join(File.dirname(__FILE__), 'proc.rb')
    
    class Sample
      def save(condition = nil, &block)
        if condition
          block.perform :success
        else
          block.perform :failure
        end
      end
    end
    
    describe Sample do
    
      before do
        @sample = Sample.new
      end
    
      it 'calls the success block when condition is true' do
        @sample.save(true) do |on|
          on.success{ 'success!' }.must_equal 'success!'
          on.failure{ 'failure!' }.must_equal false
        end
      end
    
      it 'calls the failure block when condition is false' do
        @sample.save(false) do |on|
          on.success { 'success!' }.must_equal false
          on.failure { 'failure!' }.must_equal 'failure!'
        end
      end
    
      it 'calls the callback without any block' do
        @sample.save(true) do |on|
          on.success.must_equal true
          on.failure.must_equal false
        end
      end
    
      it 'calls unknown block' do
        @sample.save(true) do |on|
          on.error { 'error' }.must_equal false
        end
      end
    
      it 'returns true from success? if condition is true' do
        @sample.save(true) do |save|
          save.success?.must_equal true
          save.failure?.must_equal false
        end
      end
    
      it 'returns false from success? if condition is false' do
        @sample.save(false) do |save|
          save.success?.must_equal false
          save.failure?.must_equal true
        end
      end
    
    end
    
    proc.rb
    class Proc
      # Defines methods in an anonymous Class based on the given object.
      # The first define_method will simply call the block if a block exists,
      # otherwise true is returned. Undefined methods always return false.
      #
      # Returns an anonymous Class
      def perform(callable)
        self === Class.new do
          method_name = callable.to_sym
          define_method(method_name) { |&block| block.nil? ? true : block.call }
          define_method("#{method_name}?") { true }
          def method_missing(method_name, *args, &block) false; end
        end.new
      end
    end
    
    View full entry
    Finished in 2nd place with a final score of 3.6/5. (View the Gist)
  • README.md

    Callback Executor

    Callback Executor is a utility class used to handle multiple block arguments which can then be executed in whatever order is necessary to complete a given task.

    Example:

    def perform_a_simple_task(&callbacks)
      CallbackExecutor.create {
        begin
          execute(:run)
          execute(:success)
        rescue Exception => e
          execute(:error, e.message, e)
        ensure
          execute(:complete)
        end
      }.run(&callbacks)
    end
    
    perform_a_simple_task do
      on(:run)      { puts 'running' }
      on(:success)  { puts 'success' }
      on(:error)    { |msg, error| puts "error: #{msg}\n#{error.backtrace.join("\n\t")}" }
      on(:complete) { puts 'complete' }
    end
    
    callback_executor.rb
    class CallbackExecutor
      def self.create(&execution_logic)
        return CallbackExecutor.new(execution_logic)
      end
    
      def initialize(execution_logic)
        @execution_logic = execution_logic
        @callbacks = {}
      end
      
      def run(&blk)
        self.instance_eval(&blk)
        self.instance_eval(&@execution_logic)
      end
      
      def on(name, &callback) 
        @callbacks[name] = callback
      end
      
      def execute(name, *args)
        unless @callbacks.has_key?(name)
          raise "no callback named #{name} found"
        end
        @callbacks[name].call(*args)
      end
    end
    
    View full entry
    Finished in 3rd place with a final score of 3.3/5. (View the Gist)
  • README.md

    MethodCallbacks

    MethodCallbacks helps you to pass multi blocks to a method, and lets the method calls yeild for each one. Let's see examples:

    require_relative 'ext_proc.rb'
    
    def sum(a, b, &block)
      result = a + b
      block.yield(:success, result)
    rescue Exception => e
      block.yield(:failure, e)
    end
    
    sum(3, 2) do
      _(:success){ |result|
        puts "Total sum is: #{result}"
      }
    
      _(:failure){ |exception|
        # Never get calls because calculation went ok
      }
    end
    
    sum('3', 2) do
      _(:success){ |result|
        # Never get calls because calculation went bad
      }
    
      _(:failure){ |exception|
        puts "Something went wrong with calculation: #{exception.message}"
      }
    end
    
    ext_proc.rb
    class Proc  
      def _(name, &block)
        @_callbacks ||= Hash.new
        @_callbacks[name] = block
      end
      
      def yield(name, *args)
        instance_eval(&self) unless @_callbacks
        @_callbacks[name] and @_callbacks[name].call(*args)
        
        args
      end
    end
    
    View full entry
    Finished in 4th place with a final score of 3.2/5. (View the Gist)
  • README
    = MultiBlock
    
    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.
    
    Load or require multi_block.rb (in Ruby 1.9) to get started.
    
    == Named Procs
    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? }
        => #
        >> a.name
        => :even?
        >> a[42]
        => false
    
    In the same way, you can create lambdas:
    
        >> b = lambda.doubler{ |e| e * 2 }
        => #
        >> b.name
        => :doubler
        >> b[21]
        => 42
        >> b.lambda?
        => true
    
    == MultiBlock Usage
    === Defining methods that use multiple blocks
    
    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
    
    === Calling methods with multiple blocks
    
    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"},
        ]
    
    == Bonus sugar: Array extension
    
    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,
        ]
    
    
    named_proc_spec.rb
    # encoding: utf-8
    require_relative 'named_proc'
    
    describe "proc" do
      it "creates a new proc as usual when called with a block" do
        a = proc{}
        a.should be_instance_of Proc
        a.lambda?.should == false
      end
      
      it "creates a named proc when a method gets called on it" do
        a = proc.brawl{}
        a.should be_a Proc
        a.should be_instance_of NamedProc
        a.lambda?.should == false
        a.name == :brawl
      end
    end
    
    describe "lambda" do
      it "creates a new lambda as usual when called with a block" do
        a = lambda{}
        a.should be_instance_of Proc
        a.lambda?.should == true
      end
      
      it "creates a named lambda when a method gets called on it" do
        a = lambda.brawl{}
        a.should be_a Proc
        a.should be_instance_of NamedProc
        a.lambda?.should == true
        a.name == :brawl
      end
    end
    
    multi_block.rb
    # encoding: utf-8
    require_relative 'named_proc'
    
    module MultiBlock
      # multiple block transformation method,
      # sorry for the method length and the code dup ;)
      def self.[](*proc_array)
        # Create hash representation, proc_array will still get used sometimes
        proc_hash = {}
        proc_array.each{ |proc|
          proc_hash[proc.name] = proc if proc.respond_to?(:name)
        }
        
        # Build yielder proc
        Proc.new{ |*proc_names_and_args|
          if proc_names_and_args.empty? # call all procs
            ret = proc_array.map(&:call)
            
            proc_array.size == 1 ? ret.first : ret
          else
            proc_names, *proc_args = *proc_names_and_args
            
            if proc_names.is_a? Hash # keys: proc_names, values: args
              proc_names.map{ |proc_name, proc_args|
                proc = proc_name.is_a?(Integer) ? proc_array[proc_name] : proc_hash[proc_name.to_sym]
                proc or raise LocalJumpError, "wrong block name given (#{proc_name})"
                
                [proc, Array(proc_args)]
              }.map{ |proc, proc_args|
                proc.call(*proc_args)
              }
              
            else
              ret = Array(proc_names).map{ |proc_name|
                proc = proc_name.is_a?(Integer) ? proc_array[proc_name] : proc_hash[proc_name.to_sym]
                proc or raise LocalJumpError, "wrong block name given (#{proc_name})"
                
                [proc, Array(proc_args)]
              }.map{ |proc, proc_args|
                proc.call(*proc_args)
              }
    
              ret.size == 1 ? ret.first : ret
              
            end
          end
        }
      end
      
      # low level mixins
      module Object
        private
        
        # to_proc helper, see README
        def blocks
          MultiBlock#[]
        end
        
        # alias procs blocks
        # alias b     blocks
      end
      
      ::Object.send :include, ::MultiBlock::Object
    
      # Bonus array mixin (if you want to)
      module Array
        # see README for an example
        def to_proc
          ::MultiBlock[*self]
        end
      end
      
      # ::Array.send :include, MultiBlock::Array
    end
    
    named_proc.rb
    # encoding: utf-8
    
    # Class for a proc that's got a name
    class NamedProc < Proc
      attr_reader :name
    
      def initialize(name)
        @name = name
        super
      end
      
      # create one from a given proc/lambda object
      def self.create(name, block, lambda = false)
        name = name.to_sym
        # sorry for this ugly hack, is there a better way to lambdafy?
        block = Module.new.send(:define_method, name.to_sym, &block) if lambda
        
        new(name, &block)
      end
      
      # Proxy object to ease named proc initialization
      module Proxy
        Proc = BasicObject.new
        def Proc.method_missing(name, &block)   NamedProc.create(name, block) end
    
        Lambda = BasicObject.new
        def Lambda.method_missing(name, &block) NamedProc.create(name, block, true) end
      end
      
      # Mixing in low level method "links"
      module Object
        private
      
        # create a proc with name if given
        def proc
          if block_given?
            super
          else
            NamedProc::Proxy::Proc
          end
        end
        
        # same for lambda
        def lambda
          if block_given?
            super
          else
            NamedProc::Proxy::Lambda
          end
        end
      end
      
      ::Object.send :include, NamedProc::Object
    end
    
    multi_block_spec.rb
    # encoding: utf-8
    require_relative 'multi_block'
    
    describe "blocks" do
      it "returns the MutliBlock constant (for calling [] on it)" do
        blocks.should == MultiBlock
      end
    end
    
    describe MultiBlock, "#[]" do
      it "yield without args: calls every block and returns array of results" do
        def null
          yield
        end
      
        null(&blocks[
          proc{5},
          proc{6},
        ]).should == [5,6]
      end
      
      it "yield with symbol: calls the specified proc, other args get passed" do
        def symbol
          yield :success, "Code Brawl!"
        end
        
        symbol(&blocks[
          proc{5},
          proc.success{|e| e.swapcase},
          proc.error{6},
        ]).should == "cODE bRAWL!"
      end
      
      it 'yield with symbol: raises LocalJumpError if proc name is wrong' do
        def wrong_name
          yield :wrong, "Code Brawl!"
        end
        
        proc do
          wrong_name(&blocks[
            proc{5},
            proc.success{|e| e.swapcase},
            proc.error{6},
          ])
        end.should raise_exception(LocalJumpError)
      end
      
      it "yield with integer: calls the n-th proc, other args get passed" do
        def integer
          yield 2
        end
        
        integer(&blocks[
          proc{5},
          proc.success{|e| e.swapcase},
          proc.error{6},
        ]).should == 6
      end
      
      it "yield with array: calls all procs, indentified by symbol or integer, other args get passed" do
        def array
          yield [:success, :error], "Code Brawl!"
        end
        
        array(&blocks[
          proc{5},
          proc.success{|e| e.swapcase},
          proc.error{|e| e.downcase},
        ]).should == ["cODE bRAWL!", "code brawl!"]
      end
      
      it "yield with hash: takes keys as proc names and passes values as proc args" do
        def hash
          yield success: "Code Brawl!", error: [500, "Internal Brawl Error"]
        end
        
        hash(&blocks[
          proc{5},
          proc.success{|e| e.swapcase},
          proc.error{|no, msg| "Error #{no}: #{msg}"},
        ]).sort.should == ["Error 500: Internal Brawl Error", "cODE bRAWL!"]
      end
    end
    
    View full entry
    Finished in 5th place with a final score of 3.2/5. (View the Gist)
  • README.md

    MultiBlock

    Ruby's syntax doesn't easily allow for passing multiple blocks to a method. This can sometimes make for awkward interfaces. Ruby's find() iterator has this problem when you choose to pass a block for handling the "not found" condition.

    MultiBlock solves this problem by allowing you to pass multiple blocks to a method by name. Here's the find() example rewritten using MultiBlock:

    require "multi_block"
    
    module Enumerable
      def multi_block_find(blocks)
        find(blocks.if_not_found, &blocks.test)
      end
      multi_block :multi_block_find, :test, :if_not_found
    end
    
    enum = [1, 2, 3]
    
    # Ruby's find()
    p enum.find(&:even?)
    p enum.find { |n| n > 3 }
    begin
      enum.find(-> { fail "Not found" }) { |n| n > 3 }
    rescue => error
      puts error.message
    end
    
    # using MultiBlock
    begin
      enum.multi_block_find do |blocks|
        blocks.test         { |n| n > 3            }
        blocks.if_not_found {     fail "Not found" }
      end
    rescue => error
      puts error.message
    end
    

    Usage

    As you can see above, you just call multi_block() with the name of the method you want to take multiple blocks. You can optionally pass the block names to accept or just leave them out to allow for any block name. The blocks will be passed in a single argument added to the end of the arguments list. Blocks are accessed by calling a method named after the block.

    You can call multi_block() on instance methods, mix-in methods, top-level methods, and class/module methods through singleton_class():

    module SomeModule
      def self.some_module_method
        # ...
      end
      singleton_class.multi_block :some_module_method
    end
    

    License

    This code is in the Public Domain. You are free to use it in any way that you like.

    multi_block.rb
    class MultiBlock < BasicObject
      def initialize(*block_names)
        @block_names = block_names
        @blocks      = { }
      end
      
      def respond_to?(method, include_private = false)
        if @block_names.empty? or @block_names.include? method
          true
        else
          super
        end
      end
      
      def method_missing(method, *_, &block)
        if @block_names.empty? or @block_names.include? method
          @blocks[method] = block if block
          @blocks[method]
        else
          super
        end
      end
    end
    
    module MultiBlockable
      def multi_block(method_name, *block_names)
        if is_a? Module
          target = self
          method = instance_method(method_name)
        else
          target = Object
          method = method(method_name)
        end
        target.send(:define_method, method_name) do |*args, &block_definitions|
          blocks = MultiBlock.new(*block_names)
          if block_definitions
            if block_definitions.arity == 1
              block_definitions.(blocks)
            else
              blocks.instance_eval(&block_definitions)
            end
          end
          bound_method = method.is_a?(UnboundMethod) ? method.bind(self) : method
          bound_method.(*args, blocks)
        end
      end
    end
    
    class Object; include MultiBlockable end
    class Module; include MultiBlockable end
    
    View full entry
    Finished in 6th place with a final score of 3.1/5. (View the Gist)
  • README.md

    ProcArrays, or How to Kind of Pass Multiple Blocks to a Method

    Wait ProcArrays, you mean BlockArrays, well no. Ruby doesn't like it when you try to call a method on a block (eg. my_method {|f| ... }.something(1)) see EOF. so instead the first thing must be a Proc, then you can chain blocks on to that as it is OK to call methods on a Proc. So here is an example:

    def call_them(procs)
      procs.call
    end
    
    # Note I used the `->` proc style because it is nicer, `proc` would still work.
    call_them ->{ "First" }.and { "Second" }
    #=> ["First", "Second"]
    

    So, above I passed two blocks/procs (proc with a block really) to a method and called them. The results of calling each proc were then returned in an Array. But we can do more interesting things than just call the Procs in the ProcArray. We can pass them arguments as well:

    def call_them(procs)
      procs.call(['dogs'], ['like', 'cats'])
    end
    
    call_them ->(noun){ puts noun }.and {|verb, noun| puts "#{verb} #{noun}" }
    #=> "dogs"
    #=> "like cats"
    

    See that I passed the list of arguments for each Proc as an Array, allowing me to pass two arguments to the last Proc/block.

    Checking the Number of Procs Passed

    ProcArray responds to #size and I've also monkey patched Proc to as well, so it doesn't matter if a single Proc or a massive ProcArray is passed you can check it's #size.

    def two_to_four_procs(procs)
      if procs.size < 2
        raise '#two_to_four_procs expects at least two procs'
      elsif procs.size > 4
        raise '#two_to_four_procs expects at most four procs'
      else
        # do something
      end
    end
    

    It's Just an Array

    Remember ProcArray is a subclass of Array so you can use normal array methods as expected.

    procs = ->(i){ i * 2 }.and {|i| i * 3 }.and {|i| i * 4 }
    
    procs.inject(2) {|a,e| e.call(a) }
    #=> 48      # ((2 * 2) * 3) * 4
    
    procs.map {|i| i.call(2) }
    #=> [4, 6, 8]
    
      # OR
      procs.call([2], [2], [2])
      #=> [4, 6, 8]
    
      # OR
      procs.call *([2] * 3)
      #=> [4, 6, 8]
    
    procs.find_all {|i| i.call(1) % 2 == 0 }
    #=> [->(i){ i * 2 }, ->(i){ i * 4 }]
    
    procs.each do |prc|
      puts prc.call(5)
    end
    #=> 10
    #=> 15
    #=> 20
    
    two, three, four = procs
    two[50]
    #=> 100
    three[100]
    #=> 300
    four[500]
    #=> 2000
    

    Appendix: Parsing Issues

    If you attempt

    def m(&block)
      block.call
    end
    
    m { puts 'First' }.and { puts 'Second' }
    # NoMethodError: undefined method `and' for nil:NilClass
    #   from (irb):11
    #   from /Users/Josh/.rbenv/versions/1.9.2-p290/bin/irb:12:in `<main>'
    

    It raises a NoMethodError because for some reason it tries to call #and on the return value of the calling the first block. This is I think due to ruby on seeing a block parsing it in a special way as (kind of) shown below.

    require 'ripper'
    
    Ripper.sexp "method {}.and {}"
    #=> [:program,
         [[:method_add_block,
           [:call,
            [:method_add_block,
             [:method_add_arg, [:fcall, [:@ident, "method", [1, 0]]], []],
             [:brace_block, nil, [[:void_stmt]]]],
            :".",
            [:@ident, "and", [1, 10]]],
           [:brace_block, nil, [[:void_stmt]]]]]]
    
    Ripper.sexp "method ->{}.and {}"
    #=> [:program,
         [[:command,
           [:@ident, "method", [1, 0]],
           [:args_add_block,
            [[:method_add_block,
              [:call,
               [:lambda, [:params, nil, nil, nil, nil, nil], [[:void_stmt]]],
               :".",
               [:@ident, "and", [1, 13]]],
              [:brace_block, nil, [[:void_stmt]]]]],
            false]]]]
    
    proc_array.rb
    class ProcArray < Array
    
      # Once a ProcArray has been created by Proc#and this method is
      # called to chain even more.  
      def and(&block)
        raise 'Need to give #and a block' unless block_given?
        
        self << block
        self
      end
      
      # The arguments for each proc should be passed in as an Array.
      #
      # @example
      #
      #   multi = ->{ puts 'Hi' }.
      #            and {|i| puts "You ordered #{i} beans" }.
      #            and { puts "Magic beans of course" }
      #
      #   multi.call(nil, [5])
      #   #=> "Hi"
      #   #=> "You ordered 5 beans"
      #   #=> "Magic beans of course"
      #
      # @return [Array] The results from each Proc being called.
      def call(*args)
        map.with_index do |prc, i|
          prc.call *args[i]
        end
      end
      
    end
    
    class Proc
      
      # Creates a new ProcArray containing this and the block passed and
      # any block chained with #and to that one.
      #
      # @example
      #
      #   chain = ->{ 1 }.and { 2 }.and { 3 }
      #   chain.each do |prc|
      #     puts prc.call
      #   end
      #
      # @return [ProcArray]
      def and(&block)  
        raise 'Need to give #and a block' unless block_given?
        
        m = ProcArray.new
        m << self
        m << block
        m
      end
      
      # This allows you to test the size of the objects passed whether it
      # is a ProcArray (which already responds to #size) or a single Proc,
      # then act on it to test for missing arguments or w/e.
      #
      # @example
      #
      #   def some_method(some_procs)
      #     puts "I was passed #{some_procs.size}"
      #     if some_procs.size < 2
      #       puts "I need 2 or more procs"
      #       exit
      #     end
      #   end
      #
      def size
        1
      end
      alias_method :length, :size
      
    end
    
    proc_array_spec.rb
    require_relative 'proc_array'
    
    gem 'minitest'
    require 'minitest/spec'
    require 'minitest/autorun'
    
    describe Proc do
      describe "#and" do
        it "returns a ProcArray" do
          a = ->{}.and {}
          a.must_be_kind_of ProcArray
        end
        
        it "contains the proc itself" do
          a = ->{}
          b = a.dup # dup because it gets modified
          a = a.and {}
          a.must_include b
        end
        
        it "contains the block passed" do
          a = ->{}
          b = ->{}
          a.and(&b).must_include b
        end
        
        it "raises an error if block not passed" do
          proc {
            ->{}.and
          }.must_raise RuntimeError
        end
      end
      
      describe "#size" do
        it "returns 1" do
          ->{}.size.must_equal 1
          ->{}.length.must_equal 1
        end
      end
    end
    
    describe ProcArray do
      describe "#and" do
        before do
          @procs = ProcArray.new
        end
      
        it "adds the block to the list" do
          a = ->{}
          @procs.and(&a).must_include(a)
        end
        
        it "raises an error if block not passed" do
          proc {
            ->{}.and
          }.must_raise RuntimeError
        end
      end
      
      describe "#call" do
        it "calls each proc in turn passing the correct arguments" do
          a = ""
          procs = ->{ a += "Hi\n" }. 
                   and {|i| a += "You ordered #{i} beans\n" }. 
                   and { a += "Magic beans of course" }
          
          procs.call(nil, [5])
          a.must_equal "Hi\nYou ordered 5 beans\nMagic beans of course"
        end
        
        it "returns an array of the results" do
          procs = ->{ 2 }.and {|i| i * 3 }.and { 4 }
          procs.call(nil, [5]).must_equal [2, 15, 4]
        end
      end
      
      describe "#map, as an example of normal Enumerable behaviour" do
        it "maps the procs" do
          procs = ->i{ i * 3 }.and {|i| i * 6 }.and {|i| i * 9 }
          procs.map {|prc| prc.call(2) }.must_equal [6, 12, 18]
        end
      end
      
      describe "#size" do
        it "returns the number of procs" do
          ->{}.and {}.size.must_equal 2
        end
      end
      
      describe "#to_a" do
        it "returns a regular array" do
          ProcArray.new.wont_be_instance_of Array
          ProcArray.new.to_a.must_be_instance_of Array
        end
      end
    
    end
    
    View full entry
    Finished in 7th place with a final score of 3.1/5. (View the Gist)
  • README.md

    Multiplex

    What is it?

    An entry for the Methods taking multiple blocks CodeBrawl.

    Oh, you want details

    The CodeBrawl description has this to say:

    For example, a method might want some code to run if an action succeeds and different code to run if it fails.
    

    Multiplex tackles this problem by having the defining code specify that certain states or outcomes are supported (success and failure in the given example). The calling code can then provide blocks for each of these states, which will be executed when prudent. Let me show you.

    Example

    class ResourceManager
      extend Multiplex
    
      def add(name)
        @resources ||= []
        @resources << name
      end
    
      multiplex :delete, [:success, :failure] do |name|
        if @resources.delete(name)
          success(name)
        else
          failure(name)
        end
      end
    end
    
    rm = ResourceManager.new
    
    rm.add :one
    
    rm.delete :one do
      success { |x| puts "deleted #{x}" }
      failure { |x| puts "couldn't delete #{x}" }
    end
    
    rm.delete :two do
      success { |x| puts "deleted #{x}" }
      failure { |x| puts "couldn't delete #{x}" }
    end
    

    This would output

    deleted one
    couldn't delete two
    

    Notice how both the defining code and the calling code use the methods success and failure. Multiplex does this by defining each state method to allow the calling code to register a block. It then redefines the methods to execute the blocks. It does for every call to the multiplexed method.

    "Isn't that dangerous/hackish/dirty/crazy/wrong?", you might ask. Yep. The focus for this exercise was a clean syntax, and it doesn't get much cleaner than calling genuine methods.

    Shortcomings

    • Hackish nature of the implementation
    • The calling code must specify a block for each registered state
    • Performance cost of defining a method for each state, twice, for every call to a multiplexed method
    • If a method exists that has the same name as a state, it will be blown away
    multiplex.rb
    module Multiplex
      def multiplex(name, states, &block)
        # everything happens in the lifespan of each method call
        define_method name do |*args, &b|
          blocks = {}
    
          # set up a method for every state that's been specified to
          # keep track of which block is tied to which state
          states.each do |state|
            define_singleton_method(state) { |&b| blocks[state] = b }
          end
    
          # runs the 'outermost' block, which will register the states
          instance_exec(&b)
    
          # redefine the state methods to call registered blocks
          states.each do |state|
            define_singleton_method(state) { |*args| blocks[state].call(*args) }
          end
    
          # finally execute it
          instance_exec(*args, &block)
    
          # clean up our methods
          states.each do |state|
            singleton_class.send :undef_method, state
          end
        end
      end
    end
    
    derp.rb
    class Derp
      extend Multiplex
    
      multiplex :doit, [:success, :failure] do |i|
        i == 42 ? success : failure
      end
    end
    
    Derp.new.doit 42 do
      success { puts "yay" }
      failure { puts "boo" }
    end
    
    Derp.new.doit 9001 do
      success { puts "yay" }
      failure { puts "boo" }
    end
    
    View full entry
    Finished in 8th place with a final score of 3.0/5. (View the Gist)
  • README.md

    BlockCapture

    BlockCapture is designed with a couple ideas in mind.

    1. It should be able to capture multiple blocks.
    2. You're program should be able to specify the types of blocks it wants to receive and have the ability to call them at the appropriate time.
    3. When a user specifies a block that the library author has not specified, they are notified of their error.
    4. BlockCapture is an interface for the user of the library and the implementor of the library and should have error messaging to reflect those two situations. (blockgiven? error vs non-blockgiven? error)
    5. Blocks can be optionally provided, so you should be able to check if a block has been provided.
    6. method_missing and capture are the only methods defined to not limit the names for methods the library author can use for capturing blocks.
    7. BlockCapture has state and behavior, and thus should be encapsulated as an object rather than as a module to be mixed in.
    block_capture.rb
    class BlockCapture
      class CaptureError < StandardError; end
    
      def capture(&block)
        instance_eval(&block)
      end
    
      def method_missing(method, *args)
        @captures ||= {}
        captures = self.class.captures
        name = captures.detect{|capture| capture == method || :"#{capture}?" == method}
        question = name && method == :"#{name}?"
    
        if name && question           # success?
          !!@captures[name]
        elsif name && block_given?    # success{ ... }
          @captures[name] = Proc.new
        elsif name                    # success
          @captures[name]
        elsif block_given?            # non_captured_method{ ... }
          raise CaptureError, "Unexpected callback #{name}. Valid callbacks are #{captures.inspect}"
        else                          # non_captured_method
          raise CaptureError, "This class does not capture #{name}."
        end
      end
    
      class << self
        attr_reader :captures
    
        def capture(name)
          @captures ||= []
          (@captures << name).uniq!
        end
      end
    end
    
    lol_connector.rb
    class LOLConnector
      attr_reader :callbacks
    
      def initialize(url)
        @callbacks = CallbackCapture.new
        callbacks.capture(&Proc.new) if block_given?
      end
    
      def connect(explode = false)
        raise if explode
        callbacks.success.call if callbacks.success?
      rescue
        callbacks.failure.call if callbacks.failure?
      ensure
        callbacks.complete.call if callbacks.complete?
      end
    
      class CallbackCapture < BlockCapture
        capture :success
        capture :failure
        capture :complete
      end
    end
    
    usage.rb
    connector = LOLConnector.new("github.com") do
      success{ puts "success!" }
      failure{ puts "failure :("}
      complete{ puts "complete o_0"}
    end
    
    connector.connect
    # success!
    # complete o_0
    
    connector.connect(true)
    # failure :(
    # complete o_0
    
    View full entry
    Finished in 9th place with a final score of 3.0/5. (View the Gist)
  • README
    My solution to "Methods taking multiple blocks" is called MultiProc, and it
    allow you to register multiple procs by name using a method chaining API.
    You pass the object as the block argument to the method (using &, as 
    MultiProc implements #to_proc).  The method receiving the block can use
    one of two APIs for call the blocks.  It can either call methods on the
    block object by name, or it can use yield or block.call with the first
    argument being a symbol for the related method.
    
    Examples:
    
    Here's a method that you can pass true or false to.  Passing true calls
    the :true block, passing false calls the :false block.  This example 
    shows the use of yield and block.call with a symbol as the first argument
    to specify which block to call.  It also shows how you can pass blocks
    to the block arguments.
    
        def a(flag, &block)
          if flag
            block.call(:true, 1, "two"){|b| [b, :foo]}
          else 
            yield :false
          end
        end
    
    Here's how you would use MultiProc to register the true and false blocks:
    
        mp = MultiProc.new.
          true{|arg1, arg2, &b| [true, arg1, arg2, b.call(:three)]}.
          false{false}
    
    This uses a fairly simple approach with method_missing being used to
    register blocks by name, and having it return self so that you can use
    it in a method chaining fashion.
    
    Calling the a methods with the MultiProc is as simple as passing it as a
    block argument using &:
    
        a(true, &mp)
        # => [true, 1, "two", [:three, :foo]]
        a(false, &mp)
        # => false
    
    The second example here calls three separate blocks: before, run, and
    after.  It uses the 2nd type of calling API, where you call blocks as
    methods by name on the block argument.
    
        def b(&block)
          block.before(:b)
          block.run(:r)
          block.after(:a)
          nil
        end
    
    Here's an example of calling the method:
    
        b(&MultiProc.new.
          run{|x| p [:run, x]}.
          before{|x| p [:before, x]}.
          after{|x| p [:after, x]})
        # => nil
        # Output:
        #  [:before, :b]
        #  [:run, :r]
        #  [:after, :a]
    
    multiproc.rb
    class MultiProc < BasicObject
      def initialize
        @procs = {}
      end
    
      def call(name, *args, &block)
        unless b = @procs[name]
          raise ArgumentError, "proc for #{name.inspect} not registered"
        end
        b.call(*args, &block)
      end
    
      def method_missing(name, &block)
        @procs[name] = block
        self
      end
    
      def to_proc
        p = Proc.new(self){|*args, &block| p.call(*args, &block)}
      end
    
      class Proc < ::Proc
        def initialize(mp)
          @multiproc = mp
          super()
        end
    
        def call(*args, &block)
          @multiproc.call(*args, &block)
        end
        alias method_missing call
      end
    end
    
    View full entry
    Finished in 10th place with a final score of 3.0/5. (View the Gist)
  • README.md

    MMMultiYield

    MMMultiYield allows your Ruby methods to take multiple named blocks with a simple DSL and yield to them independently in code. This allows for things such as callback and errback blocks, flexible case-like patterns and other stuff I've not thought of.

    Requirements

    Ruby 1.9.2 (1.8.7 and Rubinius's implementation of Kernel#caller doesn't show the class if you're called from a class body) JRuby in the future

    How to use

    Defining a method

    To define a method within current scope (e.g. within a class):

    class Foobar
      MMMulti.def :my_new_method do |mmmulti, my_arg|
        if my_arg == 'blue'
          mmmulti.yield(:callback)
        else
          mmmulti.yield(:errback)
        end
      end
    end
    

    To define it on an explicit class:

    MMMulti.def(String => :my_string_method) do |mmmulti|
      if self == 'blue'
        mmmulti.yield(:callback)
      else
        mmmulti.yield(:errback)
      end
    end
    

    Invocation

    >> Foobar.new.my_new_method 'blue' do
      def callback
        'omg it r blue'
      end
    
      def errback
        ':((( no blu'
      end
    end
    => "omg it r blue"
    
    >> 'green'.my_string_method do
      def callback
        'omg it r blue'
      end
    
      def errback
        ':((( no blu'
      end
    end
    => ":((( no blu"
    

    If the method tries to yield to a block that isn't named in the block-of-blocks, it will raise NoMethodError

    Notes

    I haven't used BlankSlate for the DSL because HOLY JESUS THAT THING IS SLOW. This is mainly a toy, so perhaps avoid naming your blocks after methods you shouldn't.

    Minitest is used for the spec. Enjoy!

    mmmulti_yield.rb
    class MMMulti
      class << self
        
        def def name, &block
          if name.is_a? Hash
            obj = name.keys[0]
            name = name.values[0]
          else
            obj = object_to_define_on(caller)
          end
          obj.send :raise, LocalJumpError unless block_given?
          obj.send :define_method, name do |*args, &block_block|
            mmmulti = MMMulti.new(block_block)
            block.call mmmulti, *args
          end
        end
        
        private
        def object_to_define_on kaller, instance = true
          /^(.+?):(\d+)(?::in `(.*)')?/ =~ kaller.shift
          case $3
          when '<main>'
            Object
          when 'singletonclass'
            object_to_define_on kaller, false
          when /^<class:(.*)>$/
            klass = object_to_define_on(kaller).const_get($1)
            klass = klass.class_eval('class << self; self; end') unless instance
            klass
          when /^<module:(.*)>$/
            object_to_define_on(kaller).const_get($1)
          end
        end
        
      end
    
      def initialize block_block
        klass = Class.new
        klass.module_exec(&block_block)
        @block_block = klass.new
      end
      
      def yield name, *args, &block
        @block_block.send name, *args, &block
      end
    end
    
    spec.rb
    require File.expand_path('mmmulti_yield')
    require 'minitest/autorun'
    
    module Foo
      MMMulti.def :module_method do |mmmulti, arg|
        arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
      end
    end
    
    class Bar
      MMMulti.def :instance_method do |mmmulti, arg|
        arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
      end
      class << self
        MMMulti.def :class_method do |mmmulti, arg|
          arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
        end
      end
    end
    
    module Moo
      class Oink
        MMMulti.def :namespaced_instance_method do |mmmulti, arg|
          arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
        end
      end
    end
    
    MMMulti.def 'main_method' do |mmmulti, arg|
      arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
    end
    
    MMMulti.def({String => :string_method}) do |mmmulti, arg|
      arg ? mmmulti.yield(:callback) : mmmulti.yield(:errback)
    end
    
    describe MMMulti do
      before do
        $result = nil
    
        @block = Proc.new {
          def callback
            $result = :ok
          end
          def errback
            $result = :error
          end
        }
      end
      
      it "should work on <main>" do
        main_method true, &@block
        $result.must_equal :ok
      end
      
      it "should work on a module" do
        Class.new.tap {|c| c.send :include, Foo }.new.module_method false, &@block
        $result.must_equal :error
      end
      
      it "should work on an instance" do
        Bar.new.instance_method true, &@block
        $result.must_equal :ok
      end
      
      it "should work on a class" do
        Bar.class_method true, &@block
        $result.must_equal :ok
      end
    
      it "should work on a namespaced class" do
        Moo::Oink.new.namespaced_instance_method true, &@block
        $result.must_equal :ok
      end
      
      it "should work on an explicit receiver" do
        'test'.string_method true, &@block
        $result.must_equal :ok
      end
      
      it "should raise no method error on an unhandled callback" do
        lambda { main_method true do
          def foobar
            'moooink'
          end
        end }.must_raise NoMethodError
      end
    end
    
    View full entry
    Finished in 11th place with a final score of 3.0/5. (View the Gist)
  • mblock.rb
    module Kernel
      # Some syntax sugar to make it nice to pass multiple blocks to a method.
      #
      # First lets find a real world example where such a behavior might be nice.
      # Looking at scope in Rails:
      # http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/scope
      #
      # We can provide a block for extensions and we can provide a block procedural
      # named scoped. Previously it might look like:
      #
      #     scope :recent, lambda { where('published_at >= ?', Time.now - 1.week) } do
      #       def dom_id
      #         'recent'
      #       end
      #     end
      #
      # Now lets re-image this call using mblock:
      #
      #     scope :recent do
      #       dynamic {where('published_at >= ?', Time.now - 1.week)}
      #       extension do
      #         def dom_id
      #           'recent'
      #         end
      #       end
      #     end
      #
      # Scope will need to be defined as follows
      #
      #     def scope(name, *scope_options)
      #       blocks = scope_options.extract_options!
      #       ....  blocks[:dynamic]  ....
      #       .... blocks[:extension] ....
      #     end
      #     mblock :scope
      #
      # The blocks are passed as a final argument to your method. It is a hash
      # where the key is the method name called in the main block
      # (dynamic, extension)
      def mblock(method_name)
        with_mblock = "mblocked_#{method_name}"
        without_mblock = "unmblocked_#{method_name}"
        eval <<-METHOD
          def #{with_mblock}(*args, &defin)
            b = MBlockBuilder.new &defin
            args.push b.blocks
            #{without_mblock} *args
          end
        METHOD
        singleton_class.send :alias_method, without_mblock, method_name.to_sym
        singleton_class.send :alias_method, method_name.to_sym, with_mblock
      end
    end
    
    class Object
      def singleton_class
        class << self
          self
        end
      end unless respond_to? :singleton_class
    end
    
    class MBlockBuilder #:nodoc:
      attr_reader :blocks
    
      def initialize(&blk)
        @blocks = {}
        instance_eval &blk
      end
    
      def method_missing(sym, &blk)
        @blocks[sym] = blk
      end
    end
    
    if __FILE__ == $0
      puts 'You should see arg1, arg2, blk1, blk2', "\n"
    
      def meth(arg1, arg2, blocks)
        puts arg1
        puts arg2
        blocks[:blk1].call
        blocks[:blk2].call
      end
      mblock :meth
    
      meth 'arg1', 'arg2' do
        blk1 {puts 'blk1'}
        blk2 {puts 'blk2'}
      end
    end
    
    View full entry
    Finished in 12th place with a final score of 2.9/5. (View the Gist)
  • README.md

    CodeBrawl contest: Methods taking multiple blocks

    This entry to the aforementioned CodeBrawl contest adds some extensions to facilitate the handling of multiple blocks (aka. Procs or lambdas) as method arguments. It is as simple as possible while maintaining a good usability.

    Usage

    def method_with_multiple_blocks(*blocks)
      blocks.extend ProcArray   # Add basic block handling to the `blocks` array
      blocks.min 1              # Require at least 2 given blocks
      blocks.max 2              # Allow at most 3 given blocks
      blocks.required :foo      # Require a block with the given name
      blocks.arities nil, 1     # Check that block #2 accepts an argument
    
      blocks[0]        # call a block by position (may be not that useful)
      blocks.bar 'baz' # call a named block (with argument)
    end
    
    bar = lambda { |baz| puts baz }   #  Create a block and ...
    bar.name = :bar                   # ... explicitly set its name
    foo = lambda { puts 'bar' }.foo   # The short syntax allows to set names that don't clash with existing methods of `Proc` (e.g. `#call`)
    
    method_with_multiple_blocks foo, bar
    
    # bar
    # baz
    

    Caveats

    Right now, there's no control over multiple Procs with the same names. This could be easily added, but currently the first Proc in a ProcArray will "win".

    multiple_blocks.rb
    module ProcArray
    
      def [](index)
        obj = super
        obj.is_a?(Proc) ? obj.call : obj
      end
    
      def arities(*arg_counts)
        each_with_index do |obj, idx|
          next unless obj.is_a? Proc
          arg_count = arg_counts[idx]
          unless arg_count.nil? || arg_count == obj.arity
            error = "Block ##{idx+1} must "
            if arg_count > 0
              error << "accept exactly #{arg_counts} arguments."
            elsif arg_count == 0
              error << 'not accept any arguments.'
            elsif arg_count < 0
              error << "accept #{arg_count.abs - 1} or more arguments."
            end
            raise error
          end
        end
      end
    
      def find_proc(name)
        find { |obj| obj.is_a?(Proc) && obj.name == name }
      end
    
      def max(proc_count)
        raise 'You supplied too many blocks.' if size > proc_count
      end
    
      def method_missing(name, *args, &block)
        proc = find_proc name
        return proc.call *args, &block unless proc.nil?
        super
      end
    
      def min(proc_count)
        raise 'You supplied too few blocks.' if size < proc_count
      end
    
      def required(*names)
        names.each do |name|
          if find_proc(name).nil?
            raise "You didn't supply a block called '#{name}'."
          end
        end
      end
    
    end
    
    module NamedProc
    
      attr_accessor :name
    
      def method_missing(name)
        @name = name
        self
      end
    
    end
    
    class Proc
      include NamedProc
    end
    
    example.rb
    def do_something(*blocks)
      blocks.extend ProcArray
      blocks.required :success, :failure, :error
      blocks.arities nil, nil, 1
    
      status = rand(3)
      
      begin
        case status
          when 0 then blocks.success
          when 1 then blocks.failure
          when 2 then raise 'error'
        end
      rescue
        blocks.error $!
      end
    end
    
    s = lambda { puts 'success' }.success
    f = lambda { puts 'failure' }.failure
    e = lambda { |error| puts "error: #{error}" }.error
    
    do_something s,f,e
    
    View full entry
    Finished in 13th place with a final score of 2.9/5. (View the Gist)
  • codebrawl.rb
    class Proc
      def exec_submethod(method, on=self)
        instance_exec &self              # running the first level of the original block in the scope of the proc
                                         # itself to record and store second level method calls
    
        on.instance_exec &@data[method]  # executing the right method inside the original scope
      end
    
      def method_missing(method, *args, &block)
        (@data ||= {})[method] = block   # recording second level method calls
      end
    end
    
    README.rb
    require "codebrawl"
    
    puts "Entry for the codebrawl contest at http://codebrawl.com/contests/methods-taking-multiple-blocks"
    
    # Defining the method that will be sent multiple blocks, do some business logic and run the corresponding block.
    #
    def do_thing(&block)
      # Business logic here, sometimes it fails sometimes it doesn't
      random_work = rand(2) == 1 ? :success : :failure 
    
      block.exec_submethod(random_work, self)
    end
    
    # This is what it is going to look like sending multiple blocks to a method
    #
    do_thing do
      success { puts "success" }
      failure { puts "failure" }
    end
    
    View full entry
    Finished in 14th place with a final score of 2.8/5. (View the Gist)
  • 0-README.markdown

    In my opinion, one of many beautiful constraints of Ruby is the ability to send only one lambda function into a method. Why beautiful? Because it stops us from suffering the madness of interfaces where you have to remember not only where exactly they are used in the method, whether or not the return values are significant, whether or not they change some bit of state, etc., but also now the order of the parameters.

    One lambda is hard enough! This isn't javascript, we do have a class system to help us out...!

    There are any number of ways to do this, the following is one idea that came to mind. It's got more magic that I usually like, but I split the implementation into a "Basic" module you can use if you just want the observable-ish behavior, and not the sugar (AKA method name pollution).

    4-procs.rb
      puts 'Injectable procs', '----------------'
      
      # Not that you'd ever want to do this, but to illustrate the point of the 
      # exercise: how to pass multiple procs into a method (well, into a slightly 
      # enhanced proc) 
      
      InjectableProc = Class.new(Proc) do
        include StateMachine::Basic
        attr_watch :state 
        attr_accessor :output
      end
      
      p = InjectableProc.new { |input| 
        p.output = input
        p.state = 0
        p.output = p.output.upcase
        p.state = 1
        p.output = p.output.gsub(/HELLO/i,'GOODBYE')
        p.state = 2
        p.output = p.output.tr('O','X')
        p.state = 3
        p.output
      }
        
      debug = lambda { |fr, to| 
        puts "callback state #{fr} -> #{to}  current output = #{p.output}"; true  
      }
      
      # reverse the output on every state change
      # why? because we can.
      (0..3).each do |st|
        p.on(:state, st, &debug)
        p.on(:state, st) { p.output = p.output.reverse }
      end
      
      puts p["Hello world"]
    
    1-statemachine.rb
    module StateMachine
    
      FailedTransition  = Class.new(StandardError)
      IllegalTransition = Class.new(StandardError)
      
      def self.included(klass)
        klass.send(:include, Basic)
        klass.extend(ClassMethods)
      end
        
      module ClassMethods
      
        # pre-define callbacks to trip illegal transition errors
        # (transitions other than defined in def_state)
        def new(*args, &blk)
          obj = allocate
          
          watched_attributes.each do |attr|
            valid = valid_transitions(attr).inject({}) { |memo, pair|
              (memo[pair[1]] ||= []) << pair[0]
              memo
            }
            valid.each do |(to, froms)|
              obj.on(attr,to) do 
                if froms.include?(obj.send(attr)) 
                  true
                else
                  raise StateMachine::IllegalTransition, "from #{obj.send(attr)} to #{to}"
                end
              end
            end
          end
          
          obj.send(:initialize, *args, &blk)
          obj
        end
        
        def valid_transitions(attr)
          _transitions[attr]
        end
        
        def def_state(attr, transitions)
          case transitions
          when Symbol
            def_state(attr, {nil => transitions})
          when Hash
            transitions.each do |(from, tos)|
              (Enumerable === tos ? tos : [tos]).each do |to|
                _add_transition attr, from, to
                _add_callback_shortcuts to
              end
            end
          else
            raise ArgumentError, "expected hash or symbol"
          end
        end
        
        private
        
        def _transitions; @_transitions ||= Hash.new {|h,k| h[k] = []}; end
        def _add_transition(attr, from, to)
          _transitions[attr] << [from, to]
        end
        def _add_callback_shortcuts(to)
          unless method_defined?("#{to}!")
            define_method "#{to}!" do |attr|
              self.send("#{attr}=", to)
            end
          end
          unless method_defined?("#{to}?")
            define_method "#{to}?" do |attr|
              self.send(attr) == to
            end
          end
          unless method_defined?("on_#{to}")
            define_method "on_#{to}" do |attr, &blk|
              on(attr, to, &blk)
            end
          end
        end
        
      end
      
      # include StateMachine::Basic if you don't want the metaprogramming magic
      # polluting your class and don't need to define valid state transitions,
      # you just want some hooks
      #  
      module Basic
      
        def self.included(klass)
          klass.extend(ClassMethods)
        end
        
        def on(attr, state, &cb)
          _cb[[attr, state]] << cb
        end
        
        private
        
        def _cb; @_cb ||= Hash.new {|h,k| h[k]=[]}; end
        
        def _trigger_callbacks_for(attr, new_state)
          _cb[[attr, new_state]].all? { |cb|
            cb.call self.send(attr), new_state
          }
        end
        
        module ClassMethods
        
          def attr_watch(*attrs)
            attrs.each do |attr|
              watched_attributes << attr
              attr_reader attr
              define_method "#{attr}=" do |value|
                if _trigger_callbacks_for(attr, value)
                  instance_variable_set("@#{attr}", value)
                else
                  raise StateMachine::FailedTransition,
                       "from #{self.send(attr)} to #{value}"
                end
              end
            end
          end
          
          def watched_attributes; @watched_attributes ||= []; end
        end
        
      end
      
    end
    
    3-fullfeatured.rb
      puts 'Full-featured usage', '----------------'
      
      class Bar
        include StateMachine
            
        # trigger for state changes
        attr_watch :foo
        
        # define valid transitions 
        def_state :foo, :init
        def_state :foo, :init => [:fail, :succeed]
        
        def initialize(state)
          self.foo = state
        end
      end
      
      b = Bar.new(:init)
      b.on_succeed(:foo) { |fr, to| puts "callback state #{fr} -> #{to}"; true  }
      b.on_fail(:foo) { |fr, to| puts "callback state  #{fr} -> #{to}"; true  }
      
      # no error: valid transition from init -> succeed
      b.succeed!(:foo)  
      # error: illegal transition from succeed -> fail
      begin; b.fail!(:foo); rescue; puts "error tripped: #{$!.class} #{$!}"; end
      
    
      b2 = Bar.new(:init)
      b2.on_succeed(:foo) { |fr, to| puts "callback state #{fr} -> #{to}"; true  }
      b2.on_fail(:foo) { |fr, to| puts "callback state #{fr} -> #{to}"; true  }
      
      # no error: valid transition from init -> fail
      b2.fail!(:foo)  
      # error: illegal transition from fail -> succeed
      begin; b2.succeed!(:foo); rescue; puts "error tripped: #{$!.class} #{$!}"; end
    
    
      # error: illegal transition in constructor
      begin; bad = Bar.new(:succeed); rescue; puts "error tripped: #{$!.class} #{$!}"; end
    
    2-basic.rb
      puts 'Basic usage', '----------------'
      
      class Foo
        include StateMachine::Basic
    
        # trigger for state changes
        attr_watch :state
      end
    
      f = Foo.new
    
      f.on(:state, :init) { |fr, to| puts "callback state #{fr} -> #{to}"; true  }
      f.on(:state, :fail) { |fr, to| puts "callback state #{fr} -> #{to}"; true  }
      # Note any callback returning false or nil raises FailedTransition
      f.on(:state, :fail) { false }   
    
      f.state = :init
      begin; f.state = :fail; rescue; puts "error tripped: #{$!.class} #{$!}"; end
    
    View full entry
    Finished in 15th place with a final score of 2.7/5. (View the Gist)
  • multiple.rb
    class Multiple
      def multiple(success)
        rand(2).odd? ? success.call : yield
      end
    end
    
    i = Multiple.new
    10.times do
       i.multiple -> { puts "success" } { puts "fail"}
    end
    
    View full entry
    Finished in 16th place with a final score of 2.5/5. (View the Gist)
  • README.md

    EHLO codebrawl

    example.rb
    class Blocc
      module Ext
        # TODO move back to Kernel
        module Object
          def blocc(&blk)
            Blocc.new &blk
          end
          alias_method :blc, :blocc
          alias_method :b, :blocc
        end
      
        module Proc
          attr_accessor :blocc_ref
          
          def blocc(&blk)
            Blocc.new(&self).blocc &blk
          end
          alias_method :blc, :blocc
          alias_method :b, :blocc
        end
      end
      Object.send :include, Ext::Object
      Proc.send :include, Ext::Proc
      
      attr_reader :blocks
      
      def initialize(&blk)
        @blocks = []
        blocc &blk if blk
      end
      
      def blocc(&blk)
        blocks << blk
        self
      end
      alias_method :blc, :blocc
      alias_method :b, :blocc
      
      def to_proc
        proc {|*args, &blk| call *args, &blk }.tap {|p| p.blocc_ref = self }
      end
      
      def call(*args, &blk)
        blocks.each {|b| b.call *args, &blk }
      end
    end
    
    def do_it(&blk)
      puts "#{blk.blocc_ref ? blk.blocc_ref.blocks.length : "no"} bloccs"
      yield "hi!"
    end
    
    l = lambda {|e| puts "lambda: #{e}" }
    p = proc {|e| puts "proc: #{e}"}
    do_it &l.b(&p).b {|e| puts "block: #{e}" }
    
    do_it &b {|e| puts "blocc#1: #{e}" }.b {|e| puts "blocc#2: #{e}" }
    
    do_it {|e| puts "..." }
    
    example2.rb
    require "ostruct"
    
    class Blocc < OpenStruct
      module Ext
        # TODO move back to Kernel
        module Object
          def blocc
            Blocc.new
          end
          alias_method :blc, :blocc
          alias_method :b, :blocc
        end
      end
      Object.send :include, Ext::Object
      
      def method_missing(mthd, *args, &block)
        if block
          super :"#{mthd}=", block
          self
        else
          super(mthd).call *args
        end
      end
      
      def to_proc
        proc do |*args|
          table.each_value {|block| block.call *args }
        end.tap do |prc|
          blc = self
          prc.singleton_class.send :define_method, :method_missing do |mthd, *args, &block|
            blc.method_missing mthd, *args, &block
          end
        end
      end
    end
    
    def foo(&block)
      block.callback "asd"
      block.call 123
    end
    
    foo &blocc.callback {|e| puts e }.errback {|e| puts "foo" }
    
    View full entry
    Finished in 17th place with a final score of 2.3/5. (View the Gist)
  • README.md

    Simple Instance Callback Hash

    This is an entry to Code Brawl: Methods taking multiple blocks

    The basic idea here is to have your callbacks setup through a method call and not sent as an argument to the method. You can then have these callbacks adapt depending on the other parameters sent through the method. After the method had been executed, it is deleted from the hash.

    Example Usage:

    class Test
      def setup_callbacks
        callback.hello do |string|
          puts string
        end
      end
    
      def request
        setup_callbacks
        callback.hello('Hello World')
      end
    end
    Test.new.request
    
    cbhash.rb
    require 'delegate'
    
    class CallbackHash < DelegateClass(Hash)
      def initialize
        super(Hash.new)
      end
    
      def method_missing(
            method_name, *arguments, &block)
        if self[method_name].nil?
          self[method_name] = block
        else
          self[method_name].call(*arguments)
          self.delete(method_name)
        end
      end
    end
    
    module Kernel
      def callback
        @cb ||= CallbackHash.new
      end
    end
    
    View full entry
    Finished in 18th place with a final score of 2.3/5. (View the Gist)
  • README.md

    First

    This is my first attempt! Please do me a favor and criticize my idea.

    Methods taking multiple blocks

    I really can't remember how I came to this solution. I think I have to say that this isn't some kind of library or gem, but an idea how you could fix the problem in a simple way. Also it won't look nice for more than two blocks!

    I thought about some ways how I could solve this, but all of them ended in a logical disaster! In the end, my point was that regular blocks are defined after the method call. So I decided to put the "alternative" block into a variable before the method call, and then pass the alternative block into the method, so it can be called from there.

    example.rb - explanation

    At first we define the method_m which takes to arguments: the second block we want to be able to call and all other arguments (in this case a).

    Then we test if the variable a is true or false. If it's true the standard block appended to the method will be executed. If a is false then block will be executed. You can easily change the block which is called by changing false to true.

    To take advantage of this, let's say "coding style", we simply define the alternate block before the method_m is called. You could also use do...end on the lambda.

    Hopefully this makes sense to anybody..

    do_end.rb
    def method_m(block, a)
      if a
        yield
      else
        block.call
      end
    end
    
    b = lambda do
      puts "alternate block"
    end; method_m(b, false) do
      puts "standard block"
    end
    
    # This looks kinda awkward and complicated.
    
    example.rb
    def method_m(block, a)
      if a
        yield
      else
        block.call
      end
    end
    
    b = lambda {puts "alternate block"}; method_m(b, false) do
      puts "standard block"
    end
    
    View full entry
    Finished in 19th place with a final score of 1.8/5. (View the Gist)
  • README.markdown

    Notes

    This is a simple method taking multiple blocks demonstration.

    The script takes one parameter: it could be an age or a birth date(DD-MM-YYYY). Then it tries to find out what age range does the person belongs to.

    When the input string is submitted, the program runs a series of tests ("modifiers") to find out what type of data has been entered: a date or a number.

    Each modifier validates input and throws and exception when the input is invalid. The recursive "Validate" method calls the cascade of modifiers according to the validator's tree. For demonstration purpose, every test result is shown.

    Usage

    $ ruby ./blocks.rb 10.10.1980
    isNotNull: passed
     isNumber: failed
     isDate: passed
      isAge: passed
       isChildAge: failed
       isAdultAge: passed
       isSeniorAge: failed
    
    
    $ ruby ./blocks.rb 8
    isNotNull: passed
     isNumber: passed
      isAge: passed
       isChildAge: passed
       isAdultAge: failed
       isSeniorAge: failed
     isDate: failed
    
    blocks.rb
    require 'Date'
    
    def Validate(input, validators, validatorTree, i = 0)
    
    	validatorTree.each {|validatorId, subValidators|
    		validator = validators[validatorId]
    		validationResult = nil
    		testPassed = true
    
    		validationResult = validator.call(input) rescue testPassed = false
    
    		puts " " * i + validatorId.to_s + ": " + (testPassed ? "passed":"failed")
    
    		Validate(validationResult, validators, subValidators, i + 1) if (testPassed && !subValidators.nil?)
    	}
    
    end
    
    checkNotNull = Proc.new { |input| raise(ArgumentError) if input.to_s.strip.empty?; input }
    
    checkNumberProc = Proc.new { |input| Integer(input) }
    checkAgeProc = Proc.new { |input| raise ArgumentError if (input > 120 || input < 0); input}
    checkForChildAgeProc = Proc.new { |input| raise ArgumentError if (input > 18); input}
    checkForAdultAgeProc = Proc.new { |input| raise ArgumentError if (input <= 18 || input >= 65); input}
    checkForSeniorAgeProc = Proc.new { |input| raise ArgumentError if (input < 65); input}
    
    checkDateProc = Proc.new { |input|  ((Date.today - Date.parse(input)) / 365.37).to_i }
    
    allTests = {:isNotNull => checkNotNull, :isNumber => checkNumberProc, :isDate => checkDateProc,
    	:isAge => checkAgeProc, :isChildAge => checkForChildAgeProc, :isAdultAge=>checkForAdultAgeProc, :isSeniorAge => checkForSeniorAgeProc}
    
    ageCheckHash = {:isAge => {:isChildAge=>nil, :isAdultAge => nil, :isSeniorAge => nil} }
    
    testTree = {:isNotNull => {:isNumber => ageCheckHash ,  :isDate => ageCheckHash } }
    
    inputStr = ARGV[0]
    
    if (inputStr.nil?)
    	puts "enter a date in DD-MM-YYYY format for birthdate or a number for age:" 
    	inputStr = gets
    end
    
    Validate inputStr, allTests, testTree
    
    View full entry
    Finished in 20th place with a final score of 1.5/5. (View the Gist)