ants
ants

Reputation: 1107

Unable to get Ruby's #any? to return false with list of nil objects

I have a very strange problem with #any? printing true for an array that only has nil objects.

The background: This is all taking part in the model - I have a list of records in an array and I set the array's element to nil if the indexed item matches certain criteria. Because I was not getting the results I was expecting (writing tests), I whacked in some debugging.

logger.debug "SIZE #{my_event_type_time_units.size}"
logger.debug "CLASS #{my_event_type_time_units.class}"
my_event_type_time_units.each { |r| logger.debug "#{r.class}" }
logger.debug "ANY? #{my_event_type_time_units.any?}"

Output

SIZE 3
CLASS Array
NilClass
NilClass
NilClass
ANY? true

As an aside, when I tried the any? with a list of nil objects, it returned false.

[nil, nil, nil].any? ## false

Can anyone tell me what I'm doing wrong. This is my first time using #any? but it can't be that hard. Can it?

any? will return true if at least one of the collection members is not false or nil

Upvotes: 1

Views: 238

Answers (2)

sethvargo
sethvargo

Reputation: 26997

You are looking at Ruby's implementation of any?, not Rails. Remember that Rails associations (specifically Arel associations) are NOT actual arrays... they are more sophisticated than that. Anything you return from a model is an association, not an array. Rails monkey-patches things to make them behave like regular Ruby objects (such has .class returning Array, but that is not always the case. Here's Rail's code for any?:

# activerecord/lib/active_record/associations/collection_association.rb, line 268
def any?
  if block_given?
    load_target.any? { |*block_args| yield(*block_args) }
  else
    !empty?
  end
end

And here's Ruby's:

static VALUE
enum_any(VALUE obj)
{
    VALUE result = Qfalse;

    rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)&result);
    return result;
}

They behave differently.

I'm not sure what you are trying to accomplish, but I suspect that any? is not the right method. I would suggest looking into include? or even compact...

Upvotes: 1

Dave Newton
Dave Newton

Reputation: 160211

Not sure which version of Rails you're using, but in < 3.1; any? is this:

  def any?
    if block_given?
      method_missing(:any?) { |*block_args| yield(*block_args) }
    else
      !empty?
    end
  end

Remember: Rails associations are not real arrays.

Upvotes: 3

Related Questions