Этот ответ в основном просто для забавы, я не советую вам его использовать.
Ruby позволяет вам проверять стек вызовов в форме обратной трассировки, но только при возникновении исключения.Итак, давайте создадим исключение, а затем вытянем руку и поймать ее, прежде чем она кому-то еще достанется, а затем: обратная трассировка - это все наше !!
Тогда все, что вам нужно сделать, - это найти обратную трассировку (массив) для любых вызовов методов нашего метода с именем "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