Use Parentheses With defined? Keyword in Ruby
defined? keyword has a bit of a gotcha that’s easy to get wrong.
defined? expression tests whether or not expression refers to anything recognizable (literal object, local variable that has been initialized, method name visible from the current scope, etc.). The return value is nil if the expression cannot be resolved. Otherwise, the return value provides information about the expression.
Note that the expression is not executed.
So a few examples…
x isn’t defined we’ll get
defined? x => nil
x is a variable, it will return
x = 1 defined? x => "local-variable"
defined? can also test expressions.
defined? x + 1 && x + 2 => "expression"
Remember, the expression is not executed
defined? x + 1 && x + 2 => "expression" x => 1
In a Rails partial template you might want to check that a local variable has
been passed to the partial before you try to do something with it.
the de-facto way of doing this.
You might also want to check the value of the variable if it does exist:
<% if defined? follower_count && follower_count > 0 %> <!-- Do A --> <% else %> <!-- Do B --> <% end %>
In this case
follower_count && follower_count > 0 as the
expression to test, and since it can execute it, the return value is
"expression" – not the return value of the expression. In this case,
always happen, regardless of whether
0 or not.
To avoid this issue, ensure the variable (or expression) you’re testing is wrapped in parentheses.
<% if defined?(follower_count) && follower_count > 0 %> <!-- Do A --> <% else %> <!-- Do B --> <% end %>