rav
rav

Reputation: 753

check if a list of object is blank in rails

lets say I have this

@objects = SampleObject.all

then I want to check if @objects is blank, I could the ff:

unless @objects.blank?
 @objects.each do |object|
 end
else
..
end

however, doing so will trigger rails to execute a SELECT count(*) query

so instead, I could do something like

unless @objects.length > 0

is there a way to override the .blank? given a particular class?

say

def self.empty?  
  self.length > 0 ?  false : true <br>
end

Upvotes: 0

Views: 1832

Answers (4)

Nimir
Nimir

Reputation: 5839

blank? uses empty?, since blank? source code:

# File activesupport/lib/active_support/core_ext/object/blank.rb, line 13
  def blank?
    respond_to?(:empty?) ? empty? : !self
  end

Now the docs about empty? says:

Returns true if the collection is empty.

If the collection has been loaded or the :counter_sql option is provided, it is equivalent to collection.size.zero?.

If the collection has not been loaded, it is equivalent to collection.exists?.

If the collection has not already been loaded and you are going to fetch the records anyway it is better to check collection.length.zero?

So, it really depends weather the collection is loaded or not? Both empty? & any? use SELEC COUNT(*) if the collection isn't loaded (reference), i think in your case SampleObject.all will be lazy loaded as @Marek said, thus the COUNT calls.

For your case i don't think you can avoid the COUNT call since you want to fetch all records and eager loading all records just to avoid a second call to db just feels pointless (solving one performance issue by causing bigger one), however if its a subset collection, i believe there will be no second COUNT call.

Upvotes: 1

Stefan
Stefan

Reputation: 114178

You can call ActiveRecord::Relation#to_a to execute the query immediately:

@objects = SampleObject.all.to_a  # runs the query, returns an array

if @objects.any?                  # no query, this is Enumerable#any?
  # ...
end

Upvotes: 0

Arup Rakshit
Arup Rakshit

Reputation: 118271

SampleObject.all gives ActiveRecord::Relation object, you can use blank? also.

blank? - Returns true if relation is blank

Thus you can write as

unless @objects.blank?
  # ...
end

Upvotes: 0

Marek Lipka
Marek Lipka

Reputation: 51151

You should use ActiveRecord::Relation#any? method:

if @objects.any?
  # ...
end

which is (in this case) negation of ActiveRecord::Relation#empty? method:

unless @objects.empty?
  # ...
end

Upvotes: 3

Related Questions