Ternary expression with "defined?" returns "expression" instead of value?
Asked Answered
D

3

7

I'm pretty new to Ruby and Rails but even after searching stack overflow and google I couldn't find an answer to this.

I've got a simple Ruby shorthand if statement that should return an integer like so:

# in the context of this erb document `amount` is defined as 5.
@c = ( defined? amount ? amount : r( 1,4 ) )

r() is a custom helper function that returns a random number between in this case 1 and 4.

The way I intend this to work is that if amount is defined, then use the number defined as amount, else generate a random number between 1 and 4 and use that instead.

When printing out @c however Ruby outputs expression rather than a number.

What do I have to do to get this working as I intended and what am I doing wrong?

Many thanks for reading!

Devonadevondra answered 6/5, 2012 at 1:57 Comment(0)
Z
9

defined? is binding to amount ? amount : r(1,4) so it is equivalent to:

defined?(amount ? amount : r(1,4))

You probably want:

defined?(amount) ? amount : r(1,4)

Actually, odds are that amount || r(1,4), or amount.nil? ? r(1,4) : amount would better match what you want, since I think you don't want this:

1.9.3p194 :001 > defined?(amount)
 => nil 
1.9.3p194 :002 > amount = nil
 => nil 
1.9.3p194 :003 > defined?(amount)
 => "local-variable" 

...in which case @c would be nil - the value of the defined variable.

Zohara answered 6/5, 2012 at 2:1 Comment(1)
Perfect, thanks a lot! Obviously I have yet to learn some more of these basics but this has been super helpful amount || r(x,y) works exactly as I wanted and is all in less characters at the same time.Devonadevondra
H
3

Use the || operator in this case:

@c = amount || r (1,4)

In your code, the defined? method operates on amount ? amount : r( 1,4 ) instead of just on amount as you intended. Also, the defined? operator probably doesn't do what you expect, have a look at this blog entry to get an idea.

Hierocracy answered 6/5, 2012 at 2:1 Comment(1)
Thanks! That blog post was very enlightening, now I see what defined? is truly useful for!Devonadevondra
A
2

You're looking for the null coalescing operator. Try this:

@c = amount || r(1,4)

This code will assign amount to @c if amount is defined. If not it will assign the result of r(1,4) to @c.

http://eddiema.ca/2010/07/07/the-null-coalescing-operator-c-ruby-js-python/

Aeneid answered 6/5, 2012 at 2:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.