Could you explain what's !! do? [duplicate] - ruby-on-rails

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does !! mean in ruby?
I found !! in Paypal gem here: https://github.com/tc/paypal_adaptive/blob/master/lib/paypal_adaptive/config.rb
like 59
but I don't understand what it does.
I know that ! means NOT, but !! doesn't make sense.
here's the screen: http://tinyurl.com/7acklhr

It forces any value to true or false depending on its "truthy" nature.
This is simply because, as you've noted, ! is the Boolean-not operator. For instance:
t = 1
puts !t # => false
puts !!t # => true
f = nil
puts !f # => true
puts !!f # => false

The !! is used to return either true or false on something that returns anything :
In Ruby, everything other than nil and false is interpreted as true. But it will not return true, it will return the value.
So if you use !, you get true or false but the opposite value of what is really is.
If you use !!, you get the true or false corresponding value.

It is used to make sure its the boolean type.
Explanation more detailed
Eg:
!!active
=> true
active = false
=> false
!!active
=> false
active = nil
=> nil
!!active
=> false

This forces a result to be true or false. As in ruby nil is not exactly false this can be useful. For instance:
def try x
if x == 1
return nil
else
return "non-nil"
end
end
p "try1" if try(1) # here you get a string printed
p "try2" if !!try(1) # here you don't

Related

Lua, if statement idiom fails to return proper boolean

local a = (true==true) and false or nil -- returns nil
local a = (true==true) and true or nil -- returns true
local a = (true==true) and not false or nil -- returns true
local a = (true==true) and not true or nil -- returns nil
Returns proper boolean when value is true, but fails when false. Why?
The boolean idiom works by using short-cut evaluation (only evaluate the second operand when necessary).
If you rewrite the expressions with explicit precedence you can see why you would get nil:
(true and false) or nil => false or nil => nil
(true and true) or nil => true or nil => true
(true and not false) or nil => true or nil => true
(true and not true) or nil => false or nil => nil
The Logical Operators section of Programming in Lua explains the idiom:
Another useful idiom is (a and b) or c (or simply a and b or c, because and has a higher precedence than or), which is equivalent to the C expression
a ? b : c
provided that b is not false. For instance, we can select the maximum of two numbers x and y with a statement like
max = (x > y) and x or y
Why can b not be false? Because the evaluation will always return false.
1 > 0 and false --> false
1 < 0 and false --> false

Switching between two boolean values in Ruby

I have the following code in a controller action, which looks at a user, and changes a boolean value to the opposite value, so if the user is true then it becomes false, and vice versa:
if current_user.enable_access
current_user.update_attribute(:enable_access, false)
else
current_user.update_attribute(:enable_access, true)
end
Is there a neater way of writing this?
How about using the toggle method that was specifically intended for this?
current_user.toggle(:enable_access)
If you want to add persistence in one character, there's also the toggle! method.
current_user.toggle!(:enable_access)
In one line, if current_user.enable_access can be only true`false`:
current_user.update_attribute(:enable_access, !current_user.enable_access)
Here's something to meditate on:
false # => false
true # => true
!false # => true
!true # => false
foo = false # => false
!foo # => true
foo = !foo # => true
foo = nil # => nil
!foo # => true
foo = !nil # => true
foo = !false # => true
Notice !!, which is a convenient way to turn a value into a true/false:
foo = !!nil # => false
foo = !!false # => false
foo = 1 # => 1
!foo # => false
!!foo # => true
foo = 'a' # => "a"
!foo # => false
!!foo # => true
0 == 1 # => false
1 == 1 # => true
'a' == '' # => false
'a' == 'a' # => true
These are the building blocks for comparisons in Ruby.
While the answer by #Зеленый is absolutely correct I wondered, that there is no DRY way to accomplish such a silly task.
The problem is that true and false in Ruby are instances of different classes, TrueClass and FalseClass respectively. That said, one can not just switch the boolean value inplace.
But what we can imagine, mediating at update_attribute source? Probably this is a shortest way to accomplish your task (please, do not use it at home, it’s a joke after all.)
current_user.tap do |cu|
cu.enable_access ^= true
end.save validate: false
I just reinvented toggle!, thanks #Dremni for pointing this out.
current_user.toggle!(:enable_access)
http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-toggle-21
I believe the DRY way to accomplish it would be to use:
current_user.enable_access = !current_user.enable_access
Then you could just write a method on a model and call it from any controller.
user.rb
def enable_user_access
self.enable_access = !self.enable_access
end
then calling it from a controller
current_user.enable_user_access

Can't use where on a column with nil value

I have an Article model
Article.last.publish
=> nil
Article.last.publish != true
=> true
Article.where("publish != ?", true)
=> []
Why am I getting an empty array there?
There are only 2 falsy values in ruby : false and nil
So, if you check the value of !nil then the output will be true
So with your first statement
Article.last.publish # its output is nil
Then your second statement
Article.last.publish != true # this is correct , since !nil = true
But the last one
Article.where("publish != ?", true)
gets converted into a query as
SELECT `articles`.* FROM `articles` WHERE (publish != 1)
which means all articles whose publish value is not true, which means false
and false is not equal to nil.
nil and false are two different falsy values.
Try Article.where(publish: false)

Ruby lazy if statement with no operator

Is it possible to do this in ruby?
variablename = true
if variablename
puts "yes!"
end
Instead of this
variablename = true
if variablename == true
puts "yes!"
end
Edit:
also considering having:
variablename = 0 #which caused my problem
I can't get that to work. Is such a style of saying if possible? I'm learning ruby now, and it is possible in PHP but im not sure how to do it right in ruby
sure, it's possible
everything except nil and false is treated as true in ruby. Meaning:
var = 0
if var
# true!
end
var = ''
if var
# true!
end
var = nil
if var
# false
end
xdazz and Vlad are correct with their answers, so you would need to catch 0 separately:
variable = false if variable.zero? # if you need 0 to be false
puts "yes!" if variable # now nil, false & 0 will be considered false
It's possible at all. In ruby, only nil and false is considered as false, any other value is true.

How do you return a boolean value for a regexp scan of an integer?

I'm looking through my object attributes for culprits that are not :
^[1-3]{3}$
What is the method used to scan integers for regexp?
Some examples:
124.to_s.match(/^[1-3]{3}$/)
=> nil
123.to_s.match(/^[1-3]{3}$/)
=>#<MatchData "123">
Since nil is considered as false, you have your boolean.
Ex:
"no yo" if 124.to_s.match(/^[1-3]{3}$/)
=> nil
"yo!" if 123.to_s.match(/^[1-3]{3}$/)
=> "yo!"
You may use also one of the following:
def is_pure_integer?(i)
i.to_i.to_s == i.to_s
end
or
'132' =~ /^\d+$/ ? true : false

Resources