In Rails, I want to check if an array is empty(arr = []).
!arr&.any?
arr&.empty?
Which is more correct?
In Rails, I want to check if an array is empty(arr = []).
!arr&.any?
arr&.empty?
Which is more correct?
Take a look at the following Ruby:
[1, 2].any? => true
[nil, false].any? => false
[nil, nil].any? => false
[1, 2].empty? => false
[nil, nil].empty? => false
Enumerable#any? is a method that asks "is there anything in this collection that’s true?" In Ruby, the existence of an object is considered true; so calling #any?
without a block is saying is there something that’s not nil or false in this collection?.
For more information see "any? != ! empty?"
In Ruby on Rails I would use blank?
. From the docs:
An object is blank if it's false, empty, or a whitespace string. For example, nil, '', ' ', [], {}, and false are all blank.
array = []
array.blank?
#=> true
Note that blank?
only works in Ruby on Rails, not in plain Ruby and that it has a slightly different behavior then empty?
. Have a look at this comparision about the responses or errors you might get from the different methods.
If you want to check that arr
contains no elements then arr.empty?
is correct.
If you want to also accept nil
or false
as empty then !arr || arr.empty?
is correct. In Ruby on Rails you can use arr.blank?
instead.
arr&.empty?
does the opposite of what you intend. nil&.empty?
is false when you want the result from nil
to be true. If arr
is nil
the safe navigation operator &.
will return nil
. Rubocop will catch this with Lint/SafeNavigationWithEmpty.
You wish to determine if an array arr
is empty; that is, if arr
equals the empty array []
. Here are some ways of doing that1:
arr == []
arr.size == 0
arr.empty?
Of these, arr.empty?
is normally the method of choice, if for no other reason than it reads best.
When choosing one method among several that work you should consider what would happen if there were a bug in your code resulting in arr
holding an object that is not an array. In particular, many bugs could result in arr
holding nil
. Should that occur arr == []
is problematic because it would return false
and merrily carry on, masking the bug from detection at that point.
nil.size == 0
and nil.empty?
both raise exceptions (because nil
does not have a method size
or empty?
), which is what you want.
You certainly do not want to use the Safe Navigation operator as it would serve only to mask errors when arr
is nil
:
arr = nil
arr&.size
#=> nil
arr&.empty?
#=> nil
Lastly arr.size == 0
has the weakness that the coder may inadvertently write arr.size = 0
, particularly if playing Call of Duty while coding (though arr.size.zero?
would be good practice as it overcomes that potential problem).
To sum up, it is difficult to find an argument for using something other than arr.empty?
to determine if an array is empty.
1 The question suggests the use of the method Array#any?. That doc references Enumerable#any?, which makes clear that, for example, [nil].any?
returns false
, yet [nil]
is not empty. Hence, any?
cannot be used to determine if an array is empty.
Since you've tagged the question with ruby-on-rails, I'm adding an answer based upon an active record collection.
Since everything other than nil
and false
is considered truthy. For active record collections this means that the behaviour would be the same for records.any?
and !records.empty?
. This is also visible when looking at the source
for ActiveRecord::Relation
:
# Returns true if there are any records. def any? return super if block_given? !empty? end
So assuming there is no block given and you're working with an ActiveRecord::Relation
:
User.active.any?
# results in the same result as
!User.active.empty?