So
shout = "gabba gabba hey"
of course does
shout.include?("gabba")
=> true
shout.include?("nothing")
=> false
Also this works
shout.include?("gabba"||"nothing")
=> true
However this doesn't
shout.include?("nothing"||"gabba")
=> false
I'm confused. Doesn't this operator work in an include at all, does it stop after evaluating the first value no matter if it returns true or false, or am I just missing something essential? Of course I could use this far longer code
shout.include?("nothing") or shout.include?("gabba")
=> true
but I'd rather have it short and concise.
You should use regexp instead:
!! (shout =~ /(gabba|nothing)/)
/(gabba|nothing)/ is a regular expression matching 'gabba' or 'nothing'
=~ returns the position of the regular expression in your string, if found
!! makes sure the result of the operation is true or false
Basically, you can't.
What you tried:
shout.include?('gabba' || 'nothing')
is equivalent to
shout.include?('gabba')
because
'gabba' || 'nothing'
# => 'gabba'
and this is how || operator works in Ruby. It returns first operand unless it's false or nil. Otherwise, it returns second operand. Since your first operand is 'gabba' string, it's being returned.
Related
I have an object with a boolean var.
field :processing, :type => Boolean
The dev before me wrote some code that says this.
:processing => nil
(He is, for some reason, setting it to nil instead of false.)
He then does this if statement
return if self.processing
dosomethingelse....
If I write code that does this
:processing => false
what happens the next time this code runs? Does dosomethingelse run?
return if self.processing
dosomethingelse....
UPDATE ===========
To many questions below so will answer here.
I added this
field :processing, :type => Boolean, :default => false
and it broke the app. When I changed to the above dosomethingelse never gets run?
return if self.processing returns. Any suggestions?
UPDATE 2 =======================================
Here is every reference to processing in my code (redacted). Also I am using MongoDB if that matters.
.where(:processing => nil).gt(:retries => 0).asc(:send_time).all.entries
if self.processing
end
return if self.processing
self.update_attributes(:processing => true)
dosomethingelse....
.where(:sent_time => nil).where(:processing => nil).gt(:retries => 0).asc(:send_time).all.entries
:processing => nil
Ruby uses truthy and falsey.
false and nil are falsey, everything else is truthy.
if true
puts "true is truthy, duh!"
else
puts "true is falsey, wtf!"
end
Output is "true is truthy, duh!"
if nil
puts "nil is truthy"
else
puts "nil is falsey"
end
Output is "nil is falsey"
if 0
puts "0 is truthy"
else
puts "0 is falsey"
end
Output is "0 is truthy"
See this explanation True and False
You could use double negating to "cast" an object to a boolean value:
!!nil # false
!!false # false
!!true # true
In general, only nil and false gives false as result. So, in if statements nil and false are interchangeable.
Yes, dosomethingelse gets run.
In ruby (almost nearly absolutely) everything is an object and every object is either "truthy" or "falsey". In general, everything is "truthy" except for the two constants, nil and false. This means that the code if foo != nil can be written more succinctly as if foo. You are branching based on the "nilness" of a particular value - similar to how you might more explicitly check for foo == null in more traditional languages.
A pattern where this shows up a lot is with ruby Hashes. By default a hash returns nil if a key is missing. So you might have code that works like this:
def foo(opts = {}) # Optional named arguments
# If :bar is not found, than => nil, so the first part of the conditional
# evalutates to false and we return the result of the second expression
bar = opts[:bar] || default_bar
end
There is an important caveat though! false and nil are not the same. Both semantically and in practice. Sometimes you actually want a boolean and then you need to be sure that you are checking explicitly for either that boolean or for nil (depending on what you are testing).
def display(opts = {})
# This will always result in fullscreen = true!
fullscreen = opts[:fullscreen] || true
end
I want to check weather variable contains a valid number or not.
I can validate correctly for null and blank but can not validate text as a "Integer"...
I tried:
if(params[:paramA].blank? || (params[:paramA].is_a?(Integer)) )
I have also tried is_numeric, is_numeric(string), is_number? and other ways...
but did not get success...
I saw such patch:
class String
def is_number?
true if Float(self) rescue false
end
end
if (params[:paramA].blank? || !params[:paramA].is_number?)
Or without the patch:
if (params[:paramA].blank? || (false if Float(params[:paramA]) rescue true))
It supports 12, -12, 12.12, 1e-3 and so on.
If your parameter is for an ActiveRecord model, then you should probably use validates_numericality_of. Otherwise...
You only want integers, right? How about:
if (params[:paramA].blank? || params[:paramA] !~ /^[+-]?\d+$/)
That is, check whether the parameter consists of an optional + or -, followed by 1 or more digits, and nothing else.
If the thing you want to do is this:
I want to check weather variable contains a valid number or not.
You can get it with regex. See it here
s = 'abc123'
if s =~ /[-.0-9]+/ # Calling String's =~ method.
puts "The String #{s} has a number in it."
else
puts "The String #{s} does not have a number in it."
end
In rails you can use the numeric? method on a String or Integer or Float which does exactly what you need.
123.numeric?
# => true
123.45.numeric?
# => true
"123".numeric?
# => true
"123.45".numeric?
# => true
"a1213".numeric?
# => false
UPDATE
My bad, I had a dirty environment, the above works if mongoid version 3 and above is loaded.
My "Project" Table have invoice as integer attribute, Here I put nil object to this attribute in DB. During evaluation nil.empty? occurs.
Code written at HAML extentions
- #project.each do |proj|
=proj.invoice if !proj.invoice.blank? || !proj.invoice.empty? || !proj.invoice.nil?
- #project_invoice=proj.invoice
=#project_invoice=0 if proj.invoice.blank? || proj.invoice.empty? || proj.invoice.nil
I receive this error while running code.
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.empty?
There's a few standard tests provided by Ruby and rails that can help, but you usually don't need to use all of them at once:
# Rails provided Object#blank? method
nil.blank? # => true
false.blank? # => true
''.blank? # => true
[ ].blank? # => true
# Ruby provided Object#nil? method
nil.nil? # => true
false.nil? # => false
''.nil? # => false
[ ].nil # => false
# Ruby class-specific #empty? method
nil.empty? # => error
false.empty? # => error
''.empty? # => true
[ ].empty? # => true
In your case the test you're probably looking for is actually a different one altogether. The opposite of blank? is present? and it comes in very handy for situations like this. You can even collapse down both of your inverted logical tests into a simple ternary query:
- #project_invoice = proj.present? ? proj.invoice : 0
More verbosely it looks like this:
- if (proj.present?)
#project_invoice = proj.invoice
- else
#project_invoice = 0
The present method verifies that the variable represents a non-nil, non-blank value of some sort.
The second condition has a misspelled variable name. It should be proj, not projt.
That would cause your issue.
if the invoice column is nill, then !proj.invoice.blank? evaluates to false, and the next test is done, !projt.invoice.empty?
since invoice is nil, you have nil.empty? which is an error, as empty? can not run on nil.
ruby-1.9.2-p0 > !nil.blank? || !nil.empty?
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.empty?
I think you are doing an overkill, since an integer should not be an array. I think you should just shorten it to only test blank?, as that catches an empty array too.
Is this is the code you are using. If this is the same code, I see a spelling mistake in the
second line.
Can you try with
=proj.invoice if !proj.invoice.blank? || !proj.invoice.empty? || !proj.invoice.nil?
def role?(role)
return !!self.roles.find_by_name(role.to_s.camelize)
end
Can you help me understand what's happening in the code above? I'm new to Rails/Ruby.
Thanks
It's negation (!) operator repeated twice.
Note that only ruby objects evaluating to false (in boolean expression) are nil and false itself.
Therefore,
some_role will be true, !some_role is false and !!some_role is true again.
nil is false, !nil is true and !!nil is false.
So, this is a "clever" way to check whether role returned from find_by_name is nil or not. (And therefore whether role with such name exists or not)
I guess, I don't have to tell you that doing this is bad for readability. You can always check if result is nil by normal means, like result.nil? or result == nil.
This is more readable. No need for the 'self' or 'return'. 'present?' is the opposite of 'nil?' so no negation is required.
def role?(role)
roles.find_by_name(role.to_s.camelize).present?
end
I find myself repeatedly looking for a clear definition of the differences of nil?, blank?, and empty? in Ruby on Rails. Here's the closest I've come:
blank? objects are false, empty, or a whitespace string. For example, "", " ", nil, [], and {} are blank.
nil? objects are instances of NilClass.
empty? objects are class-specific, and the definition varies from class to class. A string is empty if it has no characters, and an array is empty if it contains no items.
Is there anything missing, or a tighter comparison that can be made?
.nil? can be used on any object and is true if the object is nil.
.empty? can be used on strings, arrays and hashes and returns true if:
String length == 0
Array length == 0
Hash length == 0
Running .empty? on something that is nil will throw a NoMethodError.
That is where .blank? comes in. It is implemented by Rails and will operate on any object as well as work like .empty? on strings, arrays and hashes.
nil.blank? == true
false.blank? == true
[].blank? == true
{}.blank? == true
"".blank? == true
5.blank? == false
0.blank? == false
.blank? also evaluates true on strings which are non-empty but contain only whitespace:
" ".blank? == true
" ".empty? == false
Rails also provides .present?, which returns the negation of .blank?.
Array gotcha: blank? will return false even if all elements of an array are blank. To determine blankness in this case, use all? with blank?, for example:
[ nil, '' ].blank? == false
[ nil, '' ].all? &:blank? == true
I made this useful table with all the cases:
blank?, present? are provided by Rails.
Just extend Julian's table:
Ref: empty?blank?nil?傻傻分不清楚
Quick tip: !obj.blank? == obj.present?
Can be handy/easier on the eyes in some expressions
Everything that is nil? is blank?
Everything that is empty? is blank?
Nothing that is empty? is nil?
Nothing that is nil? is empty?
tl;dr -- only use blank? & present? unless you want to distinguish between "" and " "
One difference is that .nil? and .empty? are methods that are provided by the programming language Ruby, whereas .blank? is something added by the web development framework Rails.
A special case is when trying to assess if a boolean value is nil:
false.present? == false
false.blank? == true
false.nil? == false
In this case the recommendation would be to use .nil?
Just a little note about the any? recommendation: He's right that it's generally equivalent to !empty?. However, any? will return true to a string of just whitespace (ala " ").
And of course, see the 1.9 comment above, too.
Don't forget any? which is generally !empty?. In Rails I typically check for the presence of something at the end of a statement with if something or unless something then use blank? where needed since it seems to work everywhere.
nil? is a standard Ruby method that can be called on all objects and returns true if the object is nil:
b = nil
b.nil? # => true
empty? is a standard Ruby method that can be called on some objects such as Strings, Arrays and Hashes and returns true if these objects contain no element:
a = []
a.empty? # => true
b = ["2","4"]
b.empty? # => false
empty? cannot be called on nil objects.
blank? is a Rails method that can be called on nil objects as well as empty objects.
Everybody else has explained well what is the difference.
I would like to add in Ruby On Rails, it is better to use obj.blank? or obj.present? instead of obj.nil? or obj.empty?.
obj.blank? handles all types nil, '', [], {}, and returns true if values are not available and returns false if values are available on any type of object.
Though there n-number of answers available to this question but I liked the way its being explained here so posted one more answer :-)
Look at the data metric below - Its self explanatory with the various data-types used across available methods for it.
Reference: https://blog.appsignal.com/2018/09/11/differences-between-nil-empty-blank-and-present.html
exists? method can be used to check whether the data exists in the database or not. It returns boolean values either true or false.
Rails 4
an alternative to #corban-brook 's 'Array gotcha: blank?' for checking if an arrays only holds empty values and can be regarded as blank? true:
[ nil, '' ].all? &:blank? == true
one could also do:
[nil, '', "", " ",' '].reject(&:blank?).blank? == true
nil? can be used on any object. It determines if the object has any value or not, including 'blank' values.
For example:
example = nil
example.nil? # true
"".nil? # false
Basically nil? will only ever return true if the object is in fact equal to 'nil'.
empty? is only called on objects that are considered a collection. This includes things like strings (a collection of characters), hashes (a collection of key/value pairs) and arrays (a collection of arbitrary objects). empty? returns true is there are no items in the collection.
For example:
"".empty? # true
"hi".empty? # false
{}.empty? # true
{"" => ""}.empty? # false
[].empty? # true
[nil].empty? # false
nil.empty? # NoMethodError: undefined method `empty?' for nil:NilClass
Notice that empty? can't be called on nil objects as nil objects are not a collection and it will raise an exception.
Also notice that even if the items in a collection are blank, it does not mean a collection is empty.
blank? is basically a combination of nil? and empty? It's useful for checking objects that you assume are collections, but could also be nil.