0

I'm trying to clean up my code from this...

<% if defined? foo == "local-variable" %>
    <% foo = foo %>
<% else %>
    <% foo = nil %>
<% end %>

To use a ternary operator like so...

<% defined? foo == "local-variable" ? foo : nil %>

However the ternary does not run properly and defaults to the nil ... I'm rather new to using ternary operators (may have gotten into the habit of using them since they save lines)... is using defined? in a ternary possible?

mikeymurph77
  • 752
  • 1
  • 11
  • 28
  • 2
    BTW, your second statement is not equivalent to the first - the assignment is missing, i.e. `foo` is not set to `nil`. – Stefan Jul 02 '15 at 13:32
  • Is there really a need for `foo = foo` ? – limekin Jul 02 '15 at 13:41
  • @limekin no there is not I am more inclined to suggest `<% foo=nil unless local_variable_defined?(foo) %>` or as @PiotrKruczek suggested `<% foo ||= nil %>` but either way these do not pertain to the question. Also I have no idea about the implementation here or why this logic must exist in a view rather than a controller or model. – engineersmnky Jul 02 '15 at 13:48
  • Also considering that == is a method, and method calls in Ruby are evaluated from right to left, I think in your initial code `foo == 'local-variable'` is evaluated first giving `false` and then `defined? false` gets evaluated which makes the if condition return true always. – limekin Jul 02 '15 at 14:09

2 Answers2

4

It should be:

<% defined?(foo) == "local-variable" ? foo : nil %>

From documentation:

... return value provides information about the expression.

>> defined?(foo) == "local-variable"
=> true
>> defined? foo
=> "local-variable"
>> defined? (foo == "local-variable")
=> "method"

Ruby operator precedence

Roman Kiselenko
  • 43,210
  • 9
  • 91
  • 103
  • Ahh perfect I was just forgetting the parenthesis. Thanks! – mikeymurph77 Jul 02 '15 at 13:27
  • 2
    You can use `local_variable_defined?(:foo)` instead of `defined?(foo) == "local-variable"` – Stefan Jul 02 '15 at 13:39
  • `defined?` should be avoided unless you know exactly what you're doing. Since you're just using it for a local variable, I agree with @Stefan's recommendation. See my answer (http://stackoverflow.com/questions/29371966/ruby-defined-operator-works-wrong/29372162#29372162) for some of the problems with `defined?` – Max Jul 02 '15 at 14:51
2

That's not exactly an answer to your question, but something like this may help:

foo ||= nil

Translates to:

if defined? foo
  foo || foo = nil
else
  foo = nil
end
Piotr Kruczek
  • 2,384
  • 11
  • 18
  • That's not *precisely* true. That translates to `if (foo)` which means `foo` could be either `false` or `nil`. There was talk of adding `//=` which meant exactly what you're talking about here but I'm not sure where that proposal got to. – tadman Jul 02 '15 at 15:19