Prefer size over count

size doesn’t hit the database if things are loaded?. But when are things loaded? — let’s look.

Contents

Understanding loaded?

First, an example:

class PostsController < ApplicationController
  def index
    @posts = Post.all 
    @users = User.all 
    render json: @posts 
  end
end 

@users doesn’t get queried because we don’t do anything with it.

In more depth:

class PostsController < ApplicationController
  def index
    @posts = Post.all 
    puts @posts.loaded? # false 
    @posts = @posts.where(hidden: false)
    puts @posts.loaded? # false 
    some_inline_serialized_thing = @posts.map { |post| { id: post.id, title: post.title }}  
    puts @posts.loaded? # true 
  end
end 

count vs size

In this case, if we call count, we tell the object to send a count query.

A simplified version of size looks like this under the hood:

def size 
  if loaded?
    to_a.size
  else
    count 
  end
end

Whereas count will always hit the database.