Here’s one quirk I accidentally discovered in Ruby. Check this out (this is copied from my irb session):
>> defined? x => nil >> x NameError: undefined local variable or method `x' for main:Object from (irb):2 >> if false >> x = 3 >> end => nil >> defined? x => "local-variable" >> x => nil
What’s going on here?
I first checked if x variable was defined — it was not. And trying to access it resulted in an exception. Then there is an if false block that obviously is not executed.
And now for the strange part: the result of defined? x is now — quite shockingly for me — a "local-variable". Wait a minute — was the if block executed somehow?! No, it was not: the value of x is nil, not 3. Wait a (second) minute — the value of x? Wasn’t there an exception when I tried to access it last time? What is happening here?
Well, I’m not going into Ruby’s implementation details here (because I don’t know them and didn’t bother to check). I’ll just assume that what’s happened means that merely parsing the block resulted in allocating the place in some symbol table for x and now we can use it as any other local variable. BTW I checked and it works for MRI’s Ruby versions 1.8.6, 1.8.7 and 1.9.1 so I think it’s just an obscure feature, not a bug that may disappear in future versions.
But what use of such “feature”? — you may ask. Well, one could simplify conditional expressions with variable assignments. For example, instead of:
def display_address some_model
if some_model.address.street.present?
str = some_model.address.street
else
str = nil
end
if some_model.address.street_number.present?
num = some_model.address.street_number
else
num = nil
end
"#{str} #{num}"
end
one could write:
def display_address some_model
if some_model.address.street.present?
str = some_model.address.street
end
if some_model.address.street_number.present?
num = some_model.address.street_number
end
"#{str} #{num}"
end
That’s right — you can skip the else‘s and it will work just the same.
Of course, same goes for other control statements (unless, while, for etc.), for any level of nesting and for statement modifiers, too. Example:
>> for a in [] >> unless true >> while false >> b = 7 if "maybe" == "sometimes" >> end >> end >> end => [] >> defined? b => "local-variable" >> b => nil
That’s all, folks. Happy simplifying :)

