这是我的代码:
def block
puts "from block"
yield
end
block do
puts "from command line"
block do
end
end
这是输出:
from block
from command line
from block
我想知道第二个块是如何检测到它在另一个块内(同一方法)。
这样输出就是:
from block 1
from command line
from block 2
这可能吗?因为我希望嵌套块知道这一点并运行一些额外的代码。
谢谢!
答案 0 :(得分:3)
您可以使用实例变量跟踪块级别,每当您输入块时都会增加它,并在您离开块时递减它:
def block
@block_level ||= 0
@block_level += 1
puts "from block #@block_level"
yield
@block_level -= 1
end
答案 1 :(得分:2)
这个答案主要是为了好玩,我不建议您使用它。
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 :(得分:1)
yjerem说的是,只需使用ensure
来避免异常的麻烦,它听起来像一个全局变量,而不是实例变量。
def block
begin
$block_level ||= 0
$block_level += 1
puts "from block #{$block_level}"
yield
ensure
$block_level -= 1
end
end