Search code examples
rubyyield

Test ruby yield method for block execution


Whenever I pass a block to a yield method in Ruby I would like to know if the block was actually executed. For instance:

def yield_method(list)
  list.each do |item|
    yield item
  end
end

yield_method(ARGV) { |item|
  print item
}

print "executed"

I would like for the

print "executed"

statement to run only if the block passed to the yield method was executed


Solution

  • You're going to need to init a variable outside of the block and then set it from within the block, then test that.

    executed = false
    yield_method(ARGV) do |item|
       executed = true
       # whatever else
    end
    print "executed" if executed
    

    Or you can modify yield_method to return a value based on whether or not the conditions for the block to be executed were met:

    def yield_method(list)
      list.each do |item|
        yield item
      end
      list.any?
    end
    
    executed = yield_method(ARGV) { ... }
    print "executed" if executed
    

    That said, needing to know whether or not a block was executed smells bad to me - I would instead make your test a test of the conditions that would permit the block to execute (as in the second form), and write your code to semantically reflect that. For example:

    def process_argv(list)
      list.each do |item|
        yield item
      end
      list.length
    end
    
    args_processed = process_argv(ARGV) { ... }
    print "executed" if args_processed > 0
    

    This reflects that in this case, you care about whether there were args to process, rather than whether some block ended up being called. If the block has a side effect that you care about, you should test for that side effect directly, rather than assuming it based on block execution.