Here's a simpler example:
if false
x = 123
end
puts x # nil
x is defined, and has value nil. What has happened?
When the code is *parsed* (before it is executed at all, just when Ruby
is building an in-memory representation of the program), if Ruby sees an
assignment like x = ... then it marks x as being a local variable,
reserving a slot for it on the stack.
Whether the assignment is actually executed later or not is irrelevant.
From this point onwards to the end of the current scope, x is defined,
and is a local variable.
Why does ruby do this? There is a local variable / method call
ambiguity. Because you don't declare variables in Ruby, and because a
method call doesn't need parentheses after it, a bare "x" could be
either retrieving the value of x, or it could be calling the method x
with no arguments.
This simple parse-time algorithm decides in advance which you meant,
without you having to declare it.
puts x # undefined local variable or method `x'
def x
"Method x"
end
puts x # Method x
x = 123
puts x # 123
At this point it's decided that 'x' is a local variable, although you
can still force a method call instead:
puts x # 123
puts self.x # Method x
puts x() # Method x