tags:

views:

151

answers:

3
>> current_user.first_visit
=> 0
>> if current_user.first_visit
>> puts "test"
>> end
test
=> nil

Why does it print test?

+7  A: 

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.

Nakilon
@Nakilon: Please note that `.blank?` , `.empty?` are extensions provided by Rails framework (through `activesupport`) and not available in Ruby Standard or Core Lib.Also the different behaviour is because "#{false}" calls the `to_s` method.
Swanand
@swanand: `zero?` and `empty?` are there in core lib (not sure which classes you had in mind, though).
Mladen Jablanović
+4  A: 

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
Tony
+1  A: 

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

Rohit