Last Updated: February 25, 2016
·
587
· KieranP

Reduce SQL queries run when generating conditional content

If you need to check for any records before looping over them, don't do the following:

if Post.any?
  content_tag(:div) do
    Post.all.each do |post|
      ...
    end
  end
end

The example above generates two queries. One to count, another to fetch records. It's faster (granted, only fractionally, but it adds up) to do this instead:

posts = Post.all
if posts.any?
  content_tag(:div) do
    posts.each do |post|
      ...
    end
  end
end

That way, you only generate one query.

And if you want it cleaner, extract it to a helper.

def content_tag_if_any(records, tag, &block)
  return if records.none?
  content_tag(tag) do
    records.each do |record|
      yield(record)
    end
  end
end

content_tag_if_any(Post.all, :div) do |post|
  ...
end