>> current_user.first_visit
=> 0
>> if current_user.first_visit
>> puts "test"
>> end
test
=> nil
Why does it print test?
>> current_user.first_visit
=> 0
>> if current_user.first_visit
>> puts "test"
>> end
test
=> nil
Why does it print test?
In Ruby only nil
and false
can be count as false
. That's why in different cases you must use == 0
, .blank?
, .empty?
, etc.
By the way, you may place nil
instead of false
only when it's used as logical value. But in other cases they have different behavior.
irb(main):053:0> "asd#{false}asd"
=> "asdfalseasd"
irb(main):054:0> "asd#{nil}asd"
=> "asdasd"
Because they are different Ruby classes.
You can think of Ruby's if as testing either a boolean, or for the availability of data (vs nil
). The implicit conversion from 0 to false supported by C and (hence other languages like C++) was more an historical artefact from days before C had a distinct boolean type. There, it relies on 0 being a convenient sentinel value or having an intuitive meaning. For many things (e.g. some country where clothing sizes range from 0 to 8, POSIX libC function call results) zero does not convert nicely to a logically equivalent boolean, so it's not a bad thing that Ruby goes its own way.
From this perspective, the issue with your code is that current_user.first_visit - the name of which implies a boolean type - actually holds 0 and not false. Alternatively, if you had the clearly numeric current_user.visit_counter, it would be natural and correct to use one of:
current_user.visit_counter > 0
current_user.visit_counter >= 1
current_user.visit_counter != 0
You can try this
>> current_user.first_visit
=> 0
>> if current_user.first_visit != 0
>> puts "test"
>> else
>> puts "fail"
>> end
fail
=>nil
When checking for numeric values you also need to match it with the expected value