How can one block detect it inside another block?

This is my code:

def block
  puts "from block"
  yield
end

block do
  puts "from command line"
  block do

  end
end

Here is the result:

from block
from command line
from block

I wonder how the second block could detect it inside another block (the same method).

Thus, the output will be as follows:

from block 1
from command line
from block 2

Is it possible? Since I want the nested block to know about this and run some extra code.

Thank!

+3
source share
3 answers

You can track the level of a block using an instance variable, increase it every time you enter a block, and decrease it every time you leave a block:

def block
  @block_level ||= 0
  @block_level += 1

  puts "from block #@block_level"

  yield

  @block_level -= 1
end
+3
source

This answer is mostly just for fun, I do not suggest you use it.

Ruby , , . , , - , : - !

, , backtrace () "block" .

class InspectBacktrace < Exception
end

def block
  raise InspectBacktrace
rescue InspectBacktrace => e
  level = e.backtrace.count { |x| x =~ /in `block'/ }
  puts "from block #{level}"
  yield
end

block do
  puts "from command line"
  block do
    puts "from command line"
    block do
      puts "from command line"
    end
  end
end

:

from block 1
from command line
from block 2
from command line
from block 3
from command line

: Kernel#caller, . , , "block" , :

def block
  level = caller.count { |x| x =~ /^#{ Regexp.escape(__FILE__) }:\d+:in `block'$/ } + 1
  puts "from block #{level}"
  yield
end
+2

yjerem , ensure, , , .

def block
  begin
    $block_level ||= 0
    $block_level += 1
    puts "from block #{$block_level}"
    yield
  ensure
    $block_level -= 1
  end
end
+1

Source: https://habr.com/ru/post/1757046/


All Articles