Ruby (Rails 4.0.2): (1 == true) => false? - ruby

My understanding is that in the Ruby programming language, only nil and false are considered false, and EVERYTHING else is considered true.
Thus, 1 == true SHOULD return true.
I was working on a Rails 4.0.2 project using MS SQL Server (boolean field, tinyint(1)) and couldn't get the boolean working properly. The value in the DB column was 1.
Stumped, I started testing some things in the console. Here's what I got in my Rails console:
1 == true # => false
0 == true # => false
"test" == true # => false
"" == true # => false
Why is everything registering as false? I thought they were all supposed to be true?
I ended up having to do my boolean check via <attribute>.to_i == 1 to get a valid true/false value.
Am I missing something in the Ruby language or was it updated in some version I wasn't aware of? I'm using RVM, ruby 2.0.0p481 (2014-05-08 revision 45883) on a Mac machine.
Updated: 2014-10-28 09:00
After reading the excellent answers below, I understand where my thinking was wrong.
I think one of the problems is that most of the DB adapters I use (PostgreSQL, MySQL, etc...) converted boolean values in the DB for me.
For instance, in a lot of my code bases I have:
# User has an :admin boolean attribute
class User < ActiveRecord::Base
def admin?
admin == true
end
end
And I suspect this works "fine" because the DB adapter takes care of converting the DB value to a proper boolean for me.
However, I'm currently work on a project where I'm required to use MS SQL Server, and I've run into many "gotchas" with the DB adapter, one of which is I don't believe it treats boolean fields the same as the other adapters do.
Thus, I always considered any TRUTHY value to be equal to true, which it is not. I guess that's why rspec and others have moved to use be_truthy in their own syntax instead of purely be_true.
I'm just surprised it took me a few years before I ran into a problem like this!

My understanding is that in the Ruby programming language, only nil and false are considered false, and EVERYTHING else is considered true
This is true.
However,
"Thus, 1 == true SHOULD return true."
is false.
Explanation: in Ruby everything except false/nil is considered true. However when testing for equality, like x == true you're actually not testing "is this value considered true" but "is this value equal to true".
And of course 1 isn't equal to true, 1 is a number and true is a boolean value. You can read a very good blog post about equality in Ruby at "Ruby Equality And Object Comparison".
If you really, really want to test it that way, you need to convert the expression like 1 to its boolean value, which you can do by double negating it. So !!1 # => true.
So, your examples will look like this:
!!1 == true # => true
!!0 == true # => true
!!"test" == true # => true
!!"" == true # => true
However I believe it isn't necessary in most cases.
When working with MSSQL you should let Active Record do all the conversions for you. Declare the field in a migration, with type boolean, and when you do your where search in the database, do it like this:
Model.where(['attribute = ?', true])
Model.where(:attribute=> true)
This way ActiveRecord will do all the work related to converting the type to a database compatible one for you.

In terms of logical predicates every object besides nil and false are TRUTHY. What basically means that statement corresponding our predicate (condition) will be executed.
While nil and false are FALSEY predicate.
In practice it means:
if predicate
statement_a
else
statement_b
end
Whatever is not a predicate, except nil and false statement_a will be executed. Otherwise statement_b will get the jack pot.

First off, your assumption that everything in Ruby that isn't false or nil is considered true, is true.
Let's take each of your four examples:
1 == true # => false
When evaluating this expression, Ruby takes the class of the first argument, looks for the operator method and evaluates. So, for Fixnums, it evaluates whether or not 1 is equal to another Numeric number. Fixnum#== docs that is equivalent to 1.
0 == true # => false
Same as above.
"test" == true # => false
This is doing an equality test through the String class. As stated in the String#== docs, the class is tested on the right side and if it isn't a string, but responsed to to_str (true does), then the Object#=== method is used and the evaluation asks if the two are the same object, which is not the case here.
"" == true # => false
This is the same as above.
Esse's answer is correct in showing that all objects other than false and nil are true.
!!false # => false
!!nil # => false

The == is a method just like any other method in Ruby that a class uses to decide whether the passed parameter (the parameter on the right side) is equal to its object or not, just like you can define your own == method for your classes. In fact you could even modify the way == methods works for any Ruby basic object such as Fixnum if you wish.
So when you say 1 == true what you are actually saying is 1.==(true) in which case the class Fixnum doesn't like to consider the passed parameter true to be equal to its object 1.
Now when you say everything in Ruby except nil and false are considered true, the correct statement is that in Ruby only false and nil are falsey and everything else is truthy. So when Ruby has to decide whether a value or object count as or evaluates as true (such as in an if statement: if ('test')), it determines whether it is truthy or falsey, but not whether (object).==(true) returns true or false

Related

Why does an empty String returns false when comparing to boolean in ruby?

It might be a dumb question, but can someone please explain this:
if ""
true
else
false
end
=> true (OK)
!!("")
=> true (OK)
"" === true
=> false (OK)
"" == true
=> false (But why?)
Have a nice day!
The basic concept of this question is a deep misunderstanding of Ruby operators. Here's the short of it - there's no such thing as operators in Ruby! All this !, =, == and === that you throw around - these are not operators.
So what's going on?
Ruby is an object oriented language (a real one, not like that fake Java and JavaScript things) and all these fancy character sequences you think of as operators are actually method calls on the object in their left:
== method usually checks for equality - is the object on the right equal in content.
=== method is not used for "strict equality" or "identity" like it is often in other languages - some Ruby objects that implement it use it for "membership" tests, like in ranges ((1..3) === 2 ==> true) or regular expressions (/el/ === "hello" ==> true you can think of regular expressions as the group of all strings that would match), others implement it as equals.
So - how is the if working? Well, if and other "forced boolean contexts" check for "falsehood". In Ruby we recognize two false values - false and nil, everything else will run the truth branch of an if. This is actually the method ! that you also used in your second example. This method is implemented in BasicObject to return true for all objects, except if the object's type is the type of false - FalseClass or the type for nil - NilClass, in which case it returns true.
So your examples actually mean:
Check for the truthiness of "". Because that value's type is neither FalseClass or NilClass, it is always true.
For the value "", call the method ! - which will return false because the object is neither a FalseClass or a NilClass - then call ! on the result, which will return true because false is a FalseClass instance.
For the value "" call the method === with the argument true, but since it is an alias for == - call that instead (see 4).
For the value "" call the method == with the argument true. String's implementation of == will never return true for an argument that isn't a String type.
The only falsy values in Ruby are false and nil. Everything else is "truthy," but not necessarily equal to true. This includes empty objects like a String, Hash, or Array.
Pragmatically, it might help to think of == as "comparably equivalent to" rather than "equals." For example:
1 == 1.0 #=> true
This is true even though one is an Integer and one is a Float because they are comparably equivalent in value, even if they aren't the same object or of the same type.
In the same way, "" is truthy because it is not comparably equivalent to false or nil. However, it's also not the same object type as true, nor comparably equivalent to true. An empty String is simply "not falsy," which makes it truthy but not actually true.
Remember, only false and nil are falsy. Everything else, and I mean everything, is truthy even if it isn't strictly speaking true.
In Ruby, the only "falsey types" are FalseClass and NilClass, which have the instances false and nil respectively. All other values are considered "truthy". This is possibly different to what you'd expect coming from other C-like values, in which we do things like this pretty freely:
int x = get_value();
if (x) { /* implied x != 0 }
So, if you had something like this in Ruby:
puts 0 if 0 # => "0"
puts 1 if "" # => "1"
puts 2 if [] # => "2"
puts 3 if false # => nil
puts 4 if true # => "4"
puts 5 if nil # => "5"
So, if "" acts truthy, why isn't it equal to true? If that were how we defined ==, then this would also need to resolve to true then, since both values are truthy:
"1" == "2"
The difference here is that == is asking if two things are the same, which "" and true are most certainly not. Further, Ruby does not automatically convert types for you (like other languages like JavaScript do), so "" does not automatically get converted to a boolean during its comparison.

With Ruby Booleans, what are you checking for if there are no equality statements?

I am using a tutorial, and it has a conditional like this:
if Restaurant.method1
puts "XXX"
elsif Restaurant.method2
puts "YYY"
end
Both methods return a Boolean value of true or false. Similarly, for variables, I have seen something similar:
if x
puts "XXX"
else
puts "YYY"
end
I am wondering what exactly are you checking for considering that there is no equality operator (==) or assignment operator (=)? There must be some sort of equality check that perhaps hidden by the simplistic nature of Ruby, because I'm thinking this logically in my head and "If x", and "If Restaurant.method" both don't really make any sense as a conditional without some sort of check.
This is a common paradigm in programming, not a Ruby abstraction. You are checking if something is truthy. In ruby in particular, everything is truthy except false and nil. Try it yourself in your console if you want to test this:
!!1 # => true
!!0 # => true
!![] # => true
!!{} # => true
...etc, whereas
!!false # => false
!!nil # => false
Important note: this is only the case for Ruby. Other languages have different rules. For example, in some languages 0 is falsy. It's important to learn these early on when learning a new language.
Ruby has "truthy" statements. That means multiple things can evaluate to true. Everything in Ruby is true except nil and false.

Ruby writing type checker for booleans

I'm working on this exercise on Codewars (https://www.codewars.com/kata/typer-dot-js/), and I'm having trouble writing a type checker for booleans.
Based on my understanding, booleans either return true or false. But I've also read a lot of people saying that every object in Ruby is a boolean except for nil. I tried writing the method in a bunch of different ways, but I'm just not getting it. Below are some of the tries.
class Typer
def self.is_boolean? input
input == true || false
end
def self.is_boolean? input
input.class == TrueClass || FalseClass
end
def self.is_boolean? input
input == nil ? false : true
end
|| doesn't work as you expected. For example,
input == true || false
is testing if
input == true
is truthy, or if
false
is truthy. Note that the latter isn't testing input == false. And that is your main misunderstanding.
Ruby does not have a built-in method to convert values to Boolean. That may be by design, as the only false values in Ruby are false and nil. All other values (empty string, empty array, empty hash, 0) are true. There, however, a "hack" that can be used to convert values to Boolean: it’s called "bang-bang" or "double-bang" and it consists of two Boolean negation operators, like this:
!!nil
=> false
!!false
=> false
!!""
=> true
!!0
=> true
!![]
=> true
!!{}
=> true

Is there a simple way to evaluate a value to true/false without using an expression?

Is there a simple way in Ruby to get a true/false value from something without explicitly evaluating it to true or false
e.g. how would one more succinctly express
class User
def completed_initialization?
initialization_completed == 1 ? true : false
end
end
is there some way to do something along the lines of
initialization_completed.true?
There's obviously not much in it but since I'm in the zen garden of Ruby I might as well embrace it
EDIT (I've updated the example)
This question was extremely badly phrased as was very gently pointed out by #Sergio Tulentsev. The original example (below) does of course evaluate directly to a boolean. I'm still struggling to find an example of what I mean however Sergio's double-negative was in fact exactly what I was looking for.
Original example
class User
def top_responder
responses.count > 10 ? true : false
end
end
> operator already returns boolean value. So it can be just
def top_responder
responses.count > 10
end
To convert arbitrary values to booleans, I offer you this little double-negation trick.
t = 'foo'
!!t # => true
t = 1
!!t # => true
t = 0
!!t # => true
t = nil
!!t # => false
The first negation "casts" value to boolean and inverts it. That is, it will return true for nil / false and false for everything else. We need another negation to make it produce "normal" values.

What does !! mean in ruby?

Just wondering what !! is in Ruby.
Not not.
It's used to convert a value to a boolean:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
It's usually not necessary to use though since the only false values to Ruby are nil and false, so it's usually best to let that convention stand.
Think of it as
!(!some_val)
One thing that is it used for legitimately is preventing a huge chunk of data from being returned. For example you probably don't want to return 3MB of image data in your has_image? method, or you may not want to return your entire user object in the logged_in? method. Using !! converts these objects to a simple true/false.
It returns true if the object on the right is not nil and not false, false if it is nil or false
def logged_in?
!!#current_user
end
! means negate boolean state, two !s is nothing special, other than a double negation.
!true == false
# => true
It is commonly used to force a method to return a boolean. It will detect any kind of truthiness, such as string, integers and what not, and turn it into a boolean.
!"wtf"
# => false
!!"wtf"
# => true
A more real use case:
def title
"I return a string."
end
def title_exists?
!!title
end
This is useful when you want to make sure that a boolean is returned. IMHO it's kind of pointless, though, seeing that both if 'some string' and if true is the exact same flow, but some people find it useful to explicitly return a boolean.
Note that this idiom exists in other programming languages as well. C didn't have an intrinsic bool type, so all booleans were typed as int instead, with canonical values of 0 or 1. Takes this example (parentheses added for clarity):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
The "not-not" syntax converts any non-zero integer to 1, the canonical boolean true value.
In general, though, I find it much better to put in a reasonable comparison than to use this uncommon idiom:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
It's useful if you need to do an exclusive or. Copying from Matt Van Horn's answer with slight modifications:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
I used it to ensure two variables were either both nil, or both not nil.
raise "Inconsistency" if !!a ^ !!b
It is "double-negative", but the practice is being discouraged. If you're using rubocop, you'll see it complain on such code with a Style/DoubleNegation violation.
The rationale states:
As this is both cryptic and usually redundant, it should be avoided
[then paraphrasing:] Change !!something to !something.nil?
Understanding how it works can be useful if you need to convert, say, an enumeration into a boolean. I have code that does exactly that, using the classy_enum gem:
class LinkStatus < ClassyEnum::Base
def !
return true
end
end
class LinkStatus::No < LinkStatus
end
class LinkStatus::Claimed < LinkStatus
def !
return false
end
end
class LinkStatus::Confirmed < LinkStatus
def !
return false
end
end
class LinkStatus::Denied < LinkStatus
end
Then in service code I have, for example:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
Effectively the bangbang operator has become what I might otherwise have written as a method called to_bool.
Other answers have discussed what !! does and whether it is good practice or not.
However, none of the answers give the "standard Ruby way" of casting a value into a boolean.
true & variable
TrueClass, the class of the Ruby value true, implements a method &, which is documented as follows:
Returns false if obj is nil or false, true otherwise.
Why use a dirty double-negation when the standard library has you covered?

Resources