Wrapping a block with method calls that take blocks by name

I have several methods that I call this:

with_this do
  with_that do
    and_in_this_context do
      yield
    end
  end
end

I remember that there was a trick for recursively migrating such a block call. How to write a method that blocks wrapping for me?

def in_nested_contexts(&blk)
  contexts = [:with_this, :with_that, :and_in_this_context]
  # ... magic probably involving inject
end
+5
source share
1 answer

You can really use injectto create nested lambdas or procs that you can call at the end. You need your given block to be internal in the socket, so you change your array and use this block as the initial value, and then wrap each subsequent function around the result from the injection:

def in_nested_contexts(&blk)
  [:with_this, :with_that, :and_in_this_context].reverse.inject(blk) {|block, symbol|
    ->{ send symbol, &block }
  }.call
end

If you complete your methods with_this, et al with the before and after instructions puts, you can see this in action:

in_nested_contexts { puts "hello, world" }
#=> 
  with_this start
  with_that start
  context start
  hello, world
  context end
  with_that end
  with_this end
+3
source

All Articles