64

What's the best way to check if a variable is not blank in an else if condition in Ruby (not Rails)?

elsif not variable.to_s.empty?
  # do something
end

or

elsif !variable.to_s.empty?
  # do something
end

or

elsif variable.to_s.length > 0
  # do something
end
Rajkaran Mishra
  • 4,532
  • 2
  • 36
  • 61
  • 3
    Each of these ways should work. Are you asking which way is best? – Noam Hacker Mar 10 '16 at 13:14
  • 2
    The second one is most idiomatic, I think. If you were using rails, you could also do `if variable.present?` or `if !variable.blank?`, which handle both empty strings and nils. – Sergio Tulentsev Mar 10 '16 at 13:14

6 Answers6

81
string = ""

unless string.to_s.strip.empty?
  # ...
end
Lukas Baliak
  • 2,849
  • 2
  • 23
  • 26
  • 4
    @goldylucks In case you know that vatriable contains string. But variable can be nil instead and in this case strip will produce error. – Lukas Baliak Aug 20 '19 at 08:49
8

I just found out that ''.empty? returns true but ' '.empty? returns false. Even to_s.length for ' ' is not zero.

Maybe it is better to use strip as ' '.strip.empty?

Chris
  • 5,788
  • 4
  • 29
  • 40
RamanSM
  • 275
  • 3
  • 13
5

You can use either

unless var.empty?
  #do sth
end

or

unless var == ""
  #do sth
end

or all of these with if and a negator !.

three
  • 8,262
  • 3
  • 35
  • 39
4

The source of the empty? method is analogous to the following:

def empty?
    return length == 0      
end 

So, you can safely use

any_string.length != 0

Anyway, using that code inside an else if is a bit verbose, I would encourage you to define the present? method inside the String class.

class String
    def present?
        !empty?
    end
end

Now you can write your code the following way:

if some_condition
  # do something
elsif variable.to_s.present?
  # do something else
end

This way you get a clear code, without using negations or unless who are hard to read.

Of course, there is one problem here, I took the present? name (and method) from Rails. present? returns true if the object is not blank, but strings with tabs or spaces (white characters) are considered blanks. So, this present? will return true to for the following strings:

"".present?       # => false
"   ".present?    # => true
"\t\n\r".present? # => true
" blah ".present? # => true

It depends on what you want, high chances are that you want to get true for the first 3 strings, and false for the later. You could use @RamanSM approach and use strip to avoid empty spaces

class String
    def present?
        !strip.empty?
    end
end

now, present? returns false for strings with white spaces

"".present?       # => false
"   ".present?    # => false
"\t\n\r".present? # => false
" blah ".present? # => true

Note: Consider that String.present? is present in the ActiveSupport library (which ships with rails) if you add ActiveSupport or use Rails you should use ActiveSupport implementation instead.

lcjury
  • 1,158
  • 1
  • 14
  • 26
  • Should call it 'any?' to match what happens for lists and other collections. Also... ugh: patching top-level classes. – Tim Baverstock Oct 16 '20 at 13:08
  • @TimBaverstock Alternative proposal are appreciated. – lcjury Oct 17 '20 at 18:14
  • Haha. My alternative proposals would not be considered constructive. :) – Tim Baverstock Jun 15 '21 at 15:16
  • `''.present?` raises `undefined method 'present?' for "":String (NoMethodError)` unless you include `ActiveSupport` which is not a part of core ruby – jedi Jan 08 '23 at 11:40
  • @jedi read the whole answer please, it provides the implementation of `present?` so you don't have to include ActiveSupport and plenty of examples. – lcjury Jan 09 '23 at 13:49
  • @lcjury but you shouldn't propose this solution because monkey patching is something you should do only when you really have to and when you know what you're doing. In this case they should add `ActiveSupport`. What if they later add `ActiveSupport`? They will overwrite and eventually break `ActiveSupport#present?` method. – jedi Jan 10 '23 at 14:10
  • I added a note at the end of my answer for people to be careful about its usage. I have a different opinion on monkey patching. Hopefully it would help some people in the future – lcjury Jan 10 '23 at 16:10
0

If you prefer if to unless...

If you know your variable will be a String...if str[0]

With nil check...if str && str[0] OR if str&.[](0) (I prefer the latter but it might look odd to some people and requires Ruby >= 2.3).

Also...I'd be very careful about calling #to_s on anything because you could end up with unexpected results. If str turns out to be something that you weren't expecting...

str = false
str.to_s[0] # => 'f' (i.e. truthy)
str.to_s.empty? # => false

str = nil
str.to_s[0] # => nil (i.e. falsey)
str.to_s.empty? # => true

I think this caution applies to usage of #to_s in the other answer here as well. Exceptions can be your friend.

Huliax
  • 1,489
  • 3
  • 15
  • 27
-1

For the string (say abc) which is not defined/undefined we should check for abc.nil? otherwise abc.blank? will throw (NoMethodError) undefined method empty? for nil:NilClass error

Ashwini Kumar
  • 279
  • 3
  • 6