How to check if a Ruby object is a Boolean
Asked Answered
B

9

155

I can't seem to check if an object is a boolean easily. Is there something like this in Ruby?

true.is_a?(Boolean)
false.is_a?(Boolean)

Right now I'm doing this and would like to shorten it:

some_var = rand(1) == 1 ? true : false
(some_var.is_a?(TrueClass) || some_var.is_a?(FalseClass))
Bruton answered 12/6, 2010 at 9:57 Comment(1)
Similar: check-whether-a-variable-is-a-string-in-ruby?Yammer
D
148

Simplest way I can think of:

# checking whether foo is a boolean
!!foo == foo
Diagnose answered 13/6, 2010 at 19:42 Comment(17)
class X; def !; self end end ; x = X.new ; !!x == x #=> trueBehan
Yes, that's called duck typing and a core principle of OOP. I think it's a feature.Diagnose
The problem with it is that "if it walks like duck" does not imply "it quacks like duck". Correspondingly !!pseudo_bool == pseudo_bool does not imply pseudo_bool & true == pseudo_bool for example.Behan
Right, if there would be an agreed upon method to check this, like with to_ary, then it would be easier. However, I don't think this argument really counts. People could also override is_a?. In that case the only real way would be to use Module#===, as it does not call any method on the object in question. Which in turn is a violation of OOP, as all you should do is sending methods.Diagnose
Short doesn't necessarily mean simple. By which I mean, wtf is that?Selfwill
Turns foo into a boolean, checks if that's the same as foo.Diagnose
it's cryptic, but really no alternative comes closeRossen
I don't know about this answer... If foo = "" then !!foo == foo return true.Communitarian
@Communitarian No it doesn't. If foo = "", then !!foo is true, and true does not equal an empty string.Fante
Note that double negation is considered bad style by some checkers (like RuboCop).Rip
since a boolean column can be nil, and this doesn't work for nil, is there a better way?Retort
@jpwynn what makes you think this doesn't work for nil? nil != false so this works just fine for nilDalia
Considering foo as a string, it considers it as a Boolean which is not true. Am I right?Mckissick
@AboozarRajabi: foo = "bar"; !!foo == foo #=> falseMedawar
-1: This does not check if foo is a boolean, this converts the value of foo into a boolean. That is, this is not the same as `foo.is_a?(TrueClass) || foo.is_a?(FalseClass)Superpose
as @EricDuminil mentioned, this does not work well on strings foo = "bar"; !!foo == foo #=> false : -1Unsought
@PavanKumarV: The code is not really readable, but it does work on strings. It returns false, which is correct. A String isn't a boolean.Medawar
L
151

I find this to be concise and self-documenting:

[true, false].include? foo

If using Rails or ActiveSupport, you can even do a direct query using in?

foo.in? [true, false]

Checking against all possible values isn't something I'd recommend for floats, but feasible when there are only two possible values!

Lightheaded answered 9/9, 2014 at 8:44 Comment(3)
best answer by far, although I also liked foo == true or foo == false that somebody put in a comment.Chetchetah
I like this because it is less cryptic in intent than the !!foo == foo.Puglia
Downright pythonic! Definitely the most semantic answer here by far.Nemertean
D
148

Simplest way I can think of:

# checking whether foo is a boolean
!!foo == foo
Diagnose answered 13/6, 2010 at 19:42 Comment(17)
class X; def !; self end end ; x = X.new ; !!x == x #=> trueBehan
Yes, that's called duck typing and a core principle of OOP. I think it's a feature.Diagnose
The problem with it is that "if it walks like duck" does not imply "it quacks like duck". Correspondingly !!pseudo_bool == pseudo_bool does not imply pseudo_bool & true == pseudo_bool for example.Behan
Right, if there would be an agreed upon method to check this, like with to_ary, then it would be easier. However, I don't think this argument really counts. People could also override is_a?. In that case the only real way would be to use Module#===, as it does not call any method on the object in question. Which in turn is a violation of OOP, as all you should do is sending methods.Diagnose
Short doesn't necessarily mean simple. By which I mean, wtf is that?Selfwill
Turns foo into a boolean, checks if that's the same as foo.Diagnose
it's cryptic, but really no alternative comes closeRossen
I don't know about this answer... If foo = "" then !!foo == foo return true.Communitarian
@Communitarian No it doesn't. If foo = "", then !!foo is true, and true does not equal an empty string.Fante
Note that double negation is considered bad style by some checkers (like RuboCop).Rip
since a boolean column can be nil, and this doesn't work for nil, is there a better way?Retort
@jpwynn what makes you think this doesn't work for nil? nil != false so this works just fine for nilDalia
Considering foo as a string, it considers it as a Boolean which is not true. Am I right?Mckissick
@AboozarRajabi: foo = "bar"; !!foo == foo #=> falseMedawar
-1: This does not check if foo is a boolean, this converts the value of foo into a boolean. That is, this is not the same as `foo.is_a?(TrueClass) || foo.is_a?(FalseClass)Superpose
as @EricDuminil mentioned, this does not work well on strings foo = "bar"; !!foo == foo #=> false : -1Unsought
@PavanKumarV: The code is not really readable, but it does work on strings. It returns false, which is correct. A String isn't a boolean.Medawar
E
94

There is no Boolean class in Ruby, the only way to check is to do what you're doing (comparing the object against true and false or the class of the object against TrueClass and FalseClass). Can't think of why you would need this functionality though, can you explain? :)

If you really need this functionality however, you can hack it in:

module Boolean; end
class TrueClass; include Boolean; end
class FalseClass; include Boolean; end

true.is_a?(Boolean) #=> true
false.is_a?(Boolean) #=> true
Elum answered 12/6, 2010 at 10:43 Comment(5)
trying to do typecasting based on the current value.Bruton
'Why would you ever what that?' (and derivatives) is just one of the most annoying questions an engineer can make another :)Soche
+1 because I can use this in rspec like: expect(some_method?(data)).to be_a(Boolean)Vanitavanity
Other case when need to check type, is when you implement database adapter and need wrap strings with "quotes" but not numbers and booleansLobby
I'd say that being able to check the type of a variable is such a fundamentally valuable thing for a programming language, and is super important when validating user input. The fact that it's not supported without these odd hacks is... confusing to me.. Doing some research it seems to be that Ruby's way of implementing dynamic typing means there is no way to derive the type. Javascript doesn't have this issue, so I guess there is some larger story behind this..Hendecahedron
G
29

As stated above there is no boolean class just TrueClass and FalseClass however you can use any object as the subject of if/unless and everything is true except instances of FalseClass and nil

Boolean tests return an instance of the FalseClass or TrueClass

(1 > 0).class #TrueClass

The following monkeypatch to Object will tell you whether something is an instance of TrueClass or FalseClass

class Object
  def boolean?
    self.is_a?(TrueClass) || self.is_a?(FalseClass) 
  end
end

Running some tests with irb gives the following results

?> "String".boolean?
=> false
>> 1.boolean?
=> false
>> Time.now.boolean?
=> false
>> nil.boolean?
=> false
>> true.boolean?
=> true
>> false.boolean?
=> true
>> (1 ==1).boolean?
=> true
>> (1 ==2).boolean?
=> true
Glyceride answered 12/6, 2010 at 11:24 Comment(4)
Simpler just to write self == true or self == false. Those are the only instances of TrueClass and FalseClass.Doityourself
@chuck that returns the same results except for Time.now.boolean? which returns nil. Any idea why?Glyceride
Defining a class check on self in the method is somewhat not oop. You should define two versions of boolean, one for TrueClass/FalseClass and one for Object.Diagnose
The reason is that a bug in the version of Time#== in Ruby 1.8 causes a comparison to non-Time values to return nil rather than false.Doityourself
B
22

If your code can sensibly be written as a case statement, this is pretty decent:

case mybool
when TrueClass, FalseClass
  puts "It's a bool!"
else
  puts "It's something else!"
end
Broz answered 12/7, 2013 at 9:40 Comment(0)
K
7

An object that is a boolean will either have a class of TrueClass or FalseClass so the following one-liner should do the trick

mybool = true
mybool.class == TrueClass || mybool.class == FalseClass
=> true

The following would also give you true/false boolean type check result

mybool = true    
[TrueClass, FalseClass].include?(mybool.class)
=> true
Kinetics answered 10/1, 2013 at 9:52 Comment(0)
R
4

So try this out (x == true) ^ (x == false) note you need the parenthesis but this is more beautiful and compact.

It even passes the suggested like "cuak" but not a "cuak"... class X; def !; self end end ; x = X.new; (x == true) ^ (x == false)

Note: See that this is so basic that you can use it in other languages too, that doesn't provide a "thing is boolean".

Note 2: Also you can use this to say thing is one of??: "red", "green", "blue" if you add more XORS... or say this thing is one of??: 4, 5, 8, 35.

Rase answered 12/8, 2013 at 23:26 Comment(1)
Why XOR? Why not OR?Gish
E
3

This gem adds a Boolean class to Ruby with useful methods.

https://github.com/RISCfuture/boolean

Use:

require 'boolean'

Then your

true.is_a?(Boolean)
false.is_a?(Boolean)

will work exactly as you expect.

Esp answered 19/12, 2018 at 14:20 Comment(0)
S
-1

No. Not like you have your code. There isn't any class named Boolean. Now with all the answers you have you should be able to create one and use it. You do know how to create classes don't you? I only came here because I was just wondering this idea myself. Many people might say "Why? You have to just know how Ruby uses Boolean". Which is why you got the answers you did. So thanks for the question. Food for thought. Why doesn't Ruby have a Boolean class?

NameError: uninitialized constant Boolean

Keep in mind that Objects do not have types. They are classes. Objects have data. So that's why when you say data types it's a bit of a misnomer.

Also try rand 2 because rand 1 seems to always give 0. rand 2 will give 1 or 0 click run a few times here. https://repl.it/IOPx/7

Although I wouldn't know how to go about making a Boolean class myself. I've experimented with it but...

class Boolean < TrueClass
  self
end

true.is_a?(Boolean) # => false
false.is_a?(Boolean) # => false

At least we have that class now but who knows how to get the right values?

Shantell answered 24/5, 2017 at 0:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.