10

I always meet this Ruby problem, I want to write it more cleanly.

var a can be nil
a.value can also be nil
a.value has possible true or false value

if (not a.nil?) && (not a.value.nil?) && a.value == false
  puts "a value is not available"
else
  puts "a value is true"
end

The problem is that the conditional statement is too clumsy and hard to read. How can I improve the checking nil and false conditional statement?

Thanks, I am a Ruby newbie

7
  • Have you check my edited answer??? Commented Jul 25, 2013 at 7:44
  • If a.value being nil would raise an error, then why do you put that in the condition? It does not make sense because the error would be raised anyway. Commented Jul 25, 2013 at 7:47
  • it is because i am going to check a.value == false, if a.value is nil, it cannot check if that condition (undefined method for a.value), and raise exception Commented Jul 25, 2013 at 7:49
  • 1
    Um, no, you'll only get an undefined method error if a is nil, not if a.value is nil. Commented Jul 25, 2013 at 7:51
  • Or if a is a class and value is not defined. Commented Jul 25, 2013 at 8:18

6 Answers 6

20

Ruby on rails has an extension called try which allows you to write:

 if a.try(:value) == false

which is very clean. Without try, you can just write

 if a && a.value == false

If a.value is nil, it is not false, so that is ok :)

If it is possible that a.value is not defined (which would raise an exception), I would write that as follows:

if a && a.respond_to?(:value) && a.value == false

[UPDATE: after ruby 2.3]

Since ruby 2.3 there is an even shorter version:

if a&.value == false

which is almost equivalent to a.try(:value) (but is pure ruby). Differences:

  • if value does not exist, the &. operator will throw, try will just return nil (preferable or not?)(note: try! would also throw).
  • when cascading try or &. they also handle false differently. This follows logically from previous difference, try will return nil, while &. will throw because false knows no methods :P
Sign up to request clarification or add additional context in comments.

3 Comments

To be precise, this answer is not equivalent to the OP's code. If OP had defined false.value, and that has the possibility of being false, then the result would be different. But I assumed that may not be the case and gave +1 here.
You are nitpicking. It is standard practice to check for nil this way. Unfortunately this does not work if the value could be false. This will bite you when doing something like a.value ||= true --> which will always set it to true, because false and nil will return false. But in this case it is just fine.
All valid points, but it's worth noting that if you get too defensive in your programming you end up hiding actual errors. If your method only accepts an a value that's either nil or defined with a value property exposed, you're not responsible for handling oddball cases where value is not present. Let it blow up. The caller's responsible for making the correct call.
7

You can achieve it in more compacted way using Safe Navigation Operator (&.): if a&.value == false

Source : http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/

1 Comment

*Available since Ruby 2.3.0
2
  if a && a.value!=false
     puts "a value is true"
  else
     puts "a value is not available"         
  end


  or just 

  puts a && a.value!=false ? "a value is true" : "a value is not available"

3 Comments

puts a && a.value ? "a value is true" : "a value is not available" cause in ruby nil and false in an argument considered as false
(Pure) Ruby does not have a method blank?. Also, this is not equivalent to the OP's code. This code puts "a value is not available" when a.value is nil, but the OP's code puts "a value is true".
@sawa :- I remove blank? already please check my edited answer and comment on it
1

The simplest and cleanest way is to flip it and reverse it. Check for the truthy value rather than the falsey values

if a && a.value
  puts "a value is true"
else
  puts "a value is not available"
end

Of course in Rails you could do it either way by using blank? or present?

Comments

0

Your condition is redundant. If a.value is to be false, then it would not be nil.

if a.nil?.! && a.value == false
  puts "a value is not available"
else
  puts "a value is true"
end

7 Comments

If it is false, it cannot be nil.
if a.value is nil, it will throw exception
Whoa, I didn't know about Boolean#!.
yea, u are right, i think i have sth misunderstood. it will not throw exception
Having the unary prefix ! operator translate into a message send as opposed to being bultin was introduced in Ruby 1.9.0.
|
0

This will always return a boolean, if nil it will return false; if false it returns false; if true returns true. Try it out, it's nice and short:

!!a.try(:value) == false

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.