hectorsq
hectorsq

Reputation: 76976

Checking if a variable is not nil and not zero in ruby

I am using the following code to check if a variable is not nil and not zero

if(discount != nil && discount != 0) 
  ...
end

Is there a better way to do this?

Upvotes: 324

Views: 625654

Answers (19)

averydev
averydev

Reputation: 5727

In modern rails I like using positive? in this context. positive? returns a boolean, but nonzero? returns either nil or a value.

if(discount&.positive?) 
  ...
end

Examples:

With nonzero?

[nil,0, 1].map{|v| v&.nonzero?}
=> [nil, nil, 1]

And with positive?

[nil,0, 1].map{|v| v&.positive?}
=> [nil, false, true]

Upvotes: 0

NIshank
NIshank

Reputation: 127

Yes, we do have a clean way in ruby.

discount.to_f.zero?

This check handles good amount of cases i.e. discount may be nil, discount may be int 0, discount may be float 0.0, discount may be string "0.0", "0".

Upvotes: 3

Ozesh
Ozesh

Reputation: 6964

I prefer using a more cleaner approach :

val.to_i.zero?

val.to_i will return a 0 if val is a nil,

after that, all we need to do is check whether the final value is a zero.

Upvotes: 2

rewritten
rewritten

Reputation: 16435

ok, after 5 years have passed....

if discount.try :nonzero?
  ...
end

It's important to note that try is defined in the ActiveSupport gem, so it is not available in plain ruby.

Upvotes: 35

RichOrElse
RichOrElse

Reputation: 139

Alternative solution is to use Refinements, like so:

module Nothingness
  refine Numeric do
    alias_method :nothing?, :zero?
  end

  refine NilClass do
    alias_method :nothing?, :nil?
  end
end

using Nothingness

if discount.nothing?
  # do something
end

Upvotes: -1

Abhinay Reddy Keesara
Abhinay Reddy Keesara

Reputation: 10121

if discount.nil? || discount == 0
  [do something]
end

Upvotes: 0

Saroj
Saroj

Reputation: 1571

def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

If we pass "" it will return false whereas blank? returns true. Same is the case when data = false blank? returns true for nil, false, empty, or a whitespace string. So it's better to use blank? method to avoid empty string as well.

Upvotes: 2

ndnenkov
ndnenkov

Reputation: 36101

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:

if discount&.nonzero?
  # ...
end

Or postfix:

do_something if discount&.nonzero?

Upvotes: 37

pastullo
pastullo

Reputation: 4201

When dealing with a database record, I like to initialize all empty values with 0, using the migration helper:

add_column :products, :price, :integer, default: 0

Upvotes: 1

Dave G-W
Dave G-W

Reputation: 57

You can take advantage of the NilClass provided #to_i method, which will return zero for nil values:

unless discount.to_i.zero?
  # Code here
end

If discount can be fractional numbers, you can use #to_f instead, to prevent the number from being rounded to zero.

Upvotes: 2

oivoodoo
oivoodoo

Reputation: 794

You can convert your empty row to integer value and check zero?.

"".to_i.zero? => true
nil.to_i.zero? => true

Upvotes: 11

Dejan Simic
Dejan Simic

Reputation: 8120

unless discount.nil? || discount == 0
  # ...
end

Upvotes: 498

rubyprince
rubyprince

Reputation: 17793

if discount and discount != 0
  ..
end

update, it will false for discount = false

Upvotes: 3

Jeff Waltzer
Jeff Waltzer

Reputation: 529

I believe the following is good enough for ruby code. I don't think I could write a unit test that shows any difference between this and the original.

if discount != 0
end

Upvotes: -7

Raimonds Simanovskis
Raimonds Simanovskis

Reputation: 2948

if (discount||0) != 0
  #...
end

Upvotes: 18

madlep
madlep

Reputation: 49656

class Object
  def nil_zero?
    self.nil? || self == 0
  end
end

# which lets you do
nil.nil_zero? # returns true
0.nil_zero?   # returns true
1.nil_zero?   # returns false
"a".nil_zero? # returns false

unless discount.nil_zero?
  # do stuff...
end

Beware of the usual disclaimers... great power/responsibility, monkey patching leading to the dark side etc.

Upvotes: 42

Dejan Simic
Dejan Simic

Reputation: 8120

unless [nil, 0].include?(discount) 
  # ...
end

Upvotes: 29

Paige Ruten
Paige Ruten

Reputation: 176645

You could do this:

if (!discount.nil? && !discount.zero?)

The order is important here, because if discount is nil, then it will not have a zero? method. Ruby's short-circuit evaluation should prevent it from trying to evaluate discount.zero?, however, if discount is nil.

Upvotes: 25

Ed Swangren
Ed Swangren

Reputation: 124622

You could initialize discount to 0 as long as your code is guaranteed not to try and use it before it is initialized. That would remove one check I suppose, I can't think of anything else.

Upvotes: 0

Related Questions