So, we have the code:
class Foo
def bar
puts "Before existent: #{(defined? some_variable)}"
puts "Before not_existent: #{(defined? nonexistent_variable)}"
raise "error"
some_variable = 42
rescue
puts "exception"
ensure
puts "Ensure existent: #{(defined? some_variable)}"
puts "Ensure not_existent: #{(defined? nonexistent_variable)}"
end
end
And call it from irb:
> Foo.new.bar
And, that is will return:
Before existent:
Before not_existent:
exception
Ensure existent: local-variable
Ensure not_existent:
=> nil
And now is question - why? We raised exception before than some_variable
be defined.
Why it works this way? Why some_variable
is defined in ensure block? (btw, it defined as nil)
UPDATE: Thanks @Max for answer, but if we change code to use instance variable:
class Foo
def bar
puts "Before existent: #{(defined? @some_variable)}"
puts "Before not_existent: #{(defined? @nonexistent_variable)}"
raise "error"
@some_variable = 42
ensure
puts "Ensure existent: #{(defined? @some_variable)}"
puts "Ensure not_existent: #{(defined? @nonexistent_variable)}"
end
end
It works as expected:
Before existent:
Before not_existent:
Ensure existent:
Ensure not_existent:
Why?
puts @a #=> nil
, whereasputs a #NameError: undefined local variable or method
a' for main:Object`. – Fridlund