A way to track the current block level for instance block-methods, which is completely thread-safe
class MyObject | |
def block_depth=(value) | |
Thread.current[:block_depth] = value | |
end | |
def block_depth | |
Thread.current[:block_depth] || 0 | |
end | |
def track_block_depth(&block) | |
self.block_depth += 1 | |
yield | |
ensure | |
self.block_depth -= 1 | |
end | |
def method1(stuff, &block) | |
puts "This is #{stuff}... #{self.block_depth} level deep\n" | |
yield | |
end | |
def method2(stuff, &block) | |
puts "This is #{stuff}... #{self.block_depth} levels deep\n" | |
yield | |
end | |
# This will only work for Ruby 1.9 or later. For Ruby 1.8, we need to add the | |
# track_block_depth block explicitly to method1 and method2. | |
# | |
# See Ruby 1.8-compatible version of this gist at: | |
# https://gist.github.com/645809/42e6c0f44541b41d16182f0567168566aa2a40ea | |
def method_missing(method_name,*args, &block) | |
if method_name.to_s =~ /([\w\d]+)_with_block_depth/ && self.respond_to?($1) | |
self.class.send :define_method, method_name do |*args, &block| | |
self.track_block_depth do | |
self.send($1, *args, &block) | |
end | |
end | |
self.send(method_name, *args, &block) | |
else | |
super | |
end | |
end | |
def respond_to?(method_name, include_private = false) | |
if method_name.to_s =~ /([\w\d]+)_with_block_depth/ && self.respond_to?($1) | |
true | |
else | |
super | |
end | |
end | |
end | |
obj = MyObject.new | |
t1 = Thread.new do | |
obj.method1_with_block_depth "something" do | |
obj.method2_with_block_depth "something else" do | |
puts "hiya\n" | |
end | |
puts "Back to #{obj.block_depth} level deep\n" | |
end | |
end | |
t2 = Thread.new do | |
obj.method1_with_block_depth "something" do | |
obj.method2_with_block_depth "something else" do | |
puts "hiya\n" | |
end | |
puts "Back to #{obj.block_depth} level deep\n" | |
end | |
end | |
t3 = Thread.new do | |
obj.method1 "something" do | |
obj.method2 "something else" do | |
puts "hiya\n" | |
end | |
puts "Back to #{obj.block_depth} level deep\n" | |
end | |
end | |
t1.join | |
t2.join | |
t3.join | |
# => This is something... 1 level deep | |
# => This is something... 1 level deep | |
# => This is something... 0 level deep | |
# => This is something else... 2 levels deep | |
# => This is something else... 2 levels deep | |
# => This is something else... 0 levels deep | |
# => hiya | |
# => hiya | |
# => hiya | |
# => Back to 1 level deep | |
# => Back to 1 level deep | |
# => Back to 0 level deep |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment