Search code examples
rubyyield

How do I pass a block with other arguments?


def test(args,&block)
  yield
end

test 1, {puts "hello"}

Last line doesn't work. How do I pass a block with other arguments?


Solution

  • test(1){ puts "hello" }
    

    or

    test(1) do 
       puts "hello" 
    end
    

    or

    blk = proc{ puts "hello" }
    test(1, &blk)
    

    You can check out this https://pine.fm/LearnToProgram/chap_10.html

    As @Cary Swoveland suggested we can go slightly deeper.

    Any Ruby method can implicitly accept a block. And even though you didn't define it in your method signature you still can capture it and pass further.

    So, considering this idea we can do following manipulations with your method:

    def test(args, &block)
      yield
    end
    

    is the same as

    def test(args)
      yield
    end
    

    and the same as

    def test(args)
       block = Proc.new
       block.call
    end
    

    When you have this implicit block capturing you'd probably want to add extra check:

    def test(args)
       if block_given?
         block = Proc.new
         block.call
       else
         "no block"
       end
    end
    

    or

    def test(args)
       if block_given?
         yield
       else
         "no block"
       end
    end
    

    So calling these methods will return following:

    test("args")
    #=> no block
    test("args"){ "Hello World" }
    #=> "Hello World"