Skip to content

Instantly share code, notes, and snippets.

@JangoSteve
Created October 25, 2010 21:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save JangoSteve/645809 to your computer and use it in GitHub Desktop.
Save JangoSteve/645809 to your computer and use it in GitHub Desktop.
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