>> current_user.first_visit
=> 0
>> if current_user.first_visit
>> puts "test"
>> end
test
=> nil
Почему он печатает тест?
>> current_user.first_visit
=> 0
>> if current_user.first_visit
>> puts "test"
>> end
test
=> nil
Почему он печатает тест?
В Ruby только nil
можно считать аналогом false
. Нет предположения, что 0
, ""
или []
означает false
, поэтому вы должны использовать == 0
, .blank?
, .empty?
, .zero?
и т.д.
Но nil
не всегда ведет себя как false
. Например, при строчной интерполяции метод .to_s
применяется к содержимому #{}
, который работает по-разному для FalseClass
и NilClass
:
irb(main)> "qwe #{false} rty"
=> "qwe false rty"
irb(main)> "qwe #{nil} rty"
=> "qwe rty"
Вы можете думать о Ruby, если в качестве тестирования логического или для доступности данных (vs nil
). Неявное преобразование от 0 к ложному, поддерживаемое C и (следовательно, другие языки, такие как С++), было более историческим артефактом за несколько дней до того, как C имел отчетливый булевский тип. Там он полагается на то, что 0 является удобной дозорной величиной или имеет интуитивное значение. Для многих вещей (например, в какой-то стране, где размеры одежды варьируются от 0 до 8, результаты вызова функции POSIX libC), ноль не преобразуется красиво в логически эквивалентное булево, поэтому не так уж плохо, что Ruby идет своим путем.
С этой точки зрения проблема с вашим кодом заключается в том, что current_user.first_visit - имя которого подразумевает логический тип - фактически содержит 0, а не false. В качестве альтернативы, если у вас есть явно числовой current_user.visit_counter, было бы естественно и правильно использовать один из:
current_user.visit_counter > 0
current_user.visit_counter >= 1
current_user.visit_counter != 0
Вы можете попробовать это
>> current_user.first_visit
=> 0
>> if current_user.first_visit != 0
>> puts "test"
>> else
>> puts "fail"
>> end
fail
=>nil
При проверке числовых значений вам также необходимо сопоставить его с ожидаемым значением