ActiveSupport extends Object with an instance method blank?:
class Object
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
end
Could !!empty? be written as empty? instead? Is this a stylistic choice so that it reads easily as a method returning a boolean? Or is there something else?
The reason for this is that !! coerces the response from empty to a boolean. Empty can be defined differently on different objects so it is possible that someone in rails could have defined .empty? to not return a boolean. Since .blank? needs to return a boolean the !! is needed to ensure that a boolean is returned.
It is a common way to convert a truthy versus falesy value into strict true and false.
It is a common approach in Ruby to call !!(something). The result of the calculation will be boolean, not nil or something else:
!!(true) # true
!!(false) # false
!!(nil) # false
!! is used to force falsey/truthy values to false/true:
irb(main):001:0> !!nil == false
=> true
In fact, it used to be empty?. Here's the commit that changed it to !!empty?: https://github.com/rails/rails/commit/126dc47665c65cd129967cbd8a5926dddd0aa514
From the comments:
Bartuz:
Why double !! ? It returns the TrueClass / FalseClass anynway
fxn:
Because it is a dynamic language and subject to polymorphism, you just can't rely on empty? returning singletons, what you need to guarantee is that you return one no matter what.
The "improved" implementation however is incomplete, because you could just as well implement ! to return a non-boolean value:
class Foo
def !
nil
end
end
Foo.new.blank? #=> nil
To handle both methods (empty? and !), it should be implemented as:
!!(respond_to?(:empty?) ? empty? : !self)
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.
Is there any standard way to avoid truthiness in Ruby, or would I need to roll my own solution, such as
class FalseClass
def to_bool
self
end
end
class TrueClass
def to_bool
self
end
end
true.to_bool # => true
false.to_bool # => false
nil.to_bool # => NoMethodError
42.to_bool # => NoMethodError
Background: I know that to_bool would go against the permissive nature of Ruby, but I'm playing around with ternary logic, and want to avoid accidentally doing something like
require "ternary_logic"
x = UNKNOWN
do_something if x
I'm using ternary logic because I'm writing a parser of a flatmate-share web site (for personal, not commercial, use) and it's possible for some fields to be missing information, and therefore it'd be unknown whether the place meets my criteria or not. I'd try to limit the amount of code that uses the ternary logic, however.
It is not possible to influence truthiness or falsiness in Ruby. nil and false are falsy, everything else is truthy.
It's a feature that comes up every couple of years or so, but is always rejected. (For reasons that I personally don't find convincing, but I'm not the one calling the shots.)
You will have to implement your own logic system, but you cannot prohibit someone from using Ruby's logical operators on an unknown value.
I re-implemented Ruby's logic system once, for fun and to show it can be done. It should be fairly easy to extend this to ternary logic. (When I wrote this, I actually took the conformance tests from RubySpec and ported them to my implementation, and they all passed, so I'm fairly confident that it matches Ruby's semantics.)
You can take advantage of the overridable ! operator in 1.9 and the !! idiom to redefine truthiness.
Let's have a Pythonesque truthiness:
class Numeric
def !
zero?
end
end
class Array
def !
empty?
end
end
!![] #=> false
!!0 #=> false
I also made my own logic system in Ruby (for fun), and you can easily redefine truthiness:
Note, the analogs of the normal conditionals are if!/else_if!/else!
# redefine truthiness with the `truth_test` method
CustomBoolean.truth_test = proc { |b| b && b != 0 && b != [] }
if!(0) {
puts 'true'
}.
else! {
puts 'false'
}
#=> false
see: http://github.com/banister/custom_boolean
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))
Simplest way I can think of:
# checking whether foo is a boolean
!!foo == foo
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!
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
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
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
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
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.
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.
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?
I am looking for a concise way to check a value to see if it is nil or zero. Currently I am doing something like:
if (!val || val == 0)
# Is nil or zero
end
But this seems very clumsy.
Objects have a nil? method.
if val.nil? || val == 0
[do something]
end
Or, for just one instruction:
[do something] if val.nil? || val == 0
From Ruby 2.3.0 onward, you can combine the safe navigation operator (&.) with Numeric#nonzero?. &. returns nil if the instance was nil and nonzero? - if the number was 0:
unless val&.nonzero?
# Is nil or zero
end
Or postfix:
do_something unless val&.nonzero?
If you really like method names with question marks at the end:
if val.nil? || val.zero?
# do stuff
end
Your solution is fine, as are a few of the other solutions.
Ruby can make you search for a pretty way to do everything, if you're not careful.
First off I think that's about the most concise way you can check for that particular condition.
Second, to me this is a code smell that indicates a potential flaw in your design. Generally nil and zero shouldn't mean the same thing. If possible you should try to eliminate the possibility of val being nil before you hit this code, either by checking that at the beginning of the method or some other mechanism.
You might have a perfectly legitimate reason to do this in which case I think your code is good, but I'd at least consider trying to get rid of the nil check if possible.
You can use the Object.nil? to test for nil specifically (and not get caught up between false and nil). You can monkey-patch a method into Object as well.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
This is not recommended as changes to Object are difficult for coworkers to trace, and may make your code unpredictable to others.
nil.to_i returns zero, so I often do this:
val.to_i.zero?
However, you will get an exception if val is ever an object that does not respond_to #to_i.
I believe your code is incorrect; it will in fact test for three values: nil, false, and zero. This is because the !val expression is true for all values that are false, which in Ruby is nil and false.
The best I can come up with right now is
if val == nil || val == 0
# do stuff
end
Which of course is not very clever, but (very) clear.
My solution also use Refinements, minus the conditionals.
module Nothingness
refine Numeric do
alias_method :nothing?, :zero?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
if val.nothing?
# Do something
end
Short and clear
[0, nil].include?(val)
Shortest and best way should be
if val&.>(0)
# do something
end
For val&.>(0)
it returns nil when val is nil since > basically is also a method, nil equal to false in ruby. It return false when val == 0.
Rails does this via attribute query methods, where in addition to false and nil, 0 and "" also evaluate to false.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
However it has its share of detractors. http://www.joegrossberg.com/archives/002995.html
To be as idiomatic as possible, I'd suggest this.
if val.nil? or val == 0
# Do something
end
Because:
It uses the nil? method.
It uses the "or" operator, which is preferable to ||.
It doesn't use parentheses, which are not necessary in this case. Parentheses should only be used when they serve some purpose, such as overriding the precedence of certain operators.
I deal with this by defining an "is?" method, which I can then implement differently on various classes. So for Array, "is?" means "size>0"; for Fixnum it means "self != 0"; for String it means "self != ''". NilClass, of course, defines "is?" as just returning nil.
You can use case if you like:
case val with nil, 0
# do stuff
end
Then you can use anything that works with ===, which is nice sometimes. Or do something like this:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
It's not exactly good OOP, but it's very flexible and it works. My ifs usually end up as cases anyway.
Of course Enum.any?/Enum.include? kind of works too ... if you like to get really cryptic:
if [0, nil].include? val
#do stuff
end
The right thing to do is of course to define a method or function. Or, if you have to do the same thing with many values, use a combination of those nice iterators.
I really like Rails blank? method for that kind of things, but it won't return true for 0. So you can add your method:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
And it will check if some value is nil or 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Instead of monkey patching a class, you could use refinements starting in Ruby 2.1. Refinements are similar to monkey patching; in that, they allow you to modify the class, but the modification is limited to the scope you wish to use it in.
This is overkill if you want to do this check once, but if you are repeating yourself it's a great alternative to monkey patching.
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
Refinements were changed in the last minute to be scoped to the file. So earlier examples may have shown this, which will not work.
class Car
using NilOrZero
end
This is very concise:
if (val || 0) == 0
# Is nil, false, or zero.
end
It works as long as you don't mind treating false the same as nil. In the projects I've worked on, that distinction only matters once in a while. The rest of the time I personally prefer to skip .nil? and have slightly shorter code.
[Update: I don't write this sort of thing any more. It works but is too cryptic. I have tried to set right my misdeeds by changing the few places where I did it.]
By the way, I didn't use .zero? since this raises an exception if val is, say, a string. But .zero? would be fine if you know that's not the case.
This evaluates to true for nil and zero: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
In a single stretch you can do this:
[do_something] if val.to_i == 0
nil.to_i will return 0
Another solution:
if val.to_i == 0
# do stuff
end
val ||= 0
if val == 0
# do something here
end