ActiveRecord length vs size vs count
RailsのActiveRecordではrelationに対してlength, size, countのいずれでもクエリの結果の件数を取得できるが挙動に違いがある
結論
キャッシュを使うならsize
キャッシュを使わないならcount
lengthはクエリの結果をloadするので件数取得のためだけには使わない
length
recordsにdelegateされている
https://github.com/rails/rails/blob/v6.1.4/activerecord/lib/active_record/relation/delegation.rb#L88-L91
ActiveRecord::Relation#recordsはレコードをloadする
code:ruby
def records # :nodoc:
load
@records
end
code:ruby
def load(&block)
unless loaded?
@records = exec_queries(&block)
@loaded = true
end
self
end
https://github.com/rails/rails/blob/v6.1.4/activerecord/lib/active_record/relation.rb#L629-L636
つまり、クエリを実行し、その結果として返ってきたArrayのArray#lengthを呼ぶ
count
ActiveRecord::RelationがincludeしているActiveRecord::Relation::Calculationsの#count
relationがloaded?かどうかはチェックせずにSQLのCOUNTをDBに発行する
size
クエリの結果がloaded?かどうかで挙動が変わる
https://github.com/rails/rails/blob/v6.1.4/activerecord/lib/active_record/relation.rb#L259-L261
code:ruby
def size
loaded? ? @records.length : count(:all)
end
loadされていたらキャッシュしている@recordsのArray#lengthを呼ぶ
loadされていなければActiveRecord::RelationがincludeしているActiveRecord::Relation::Calculationsの#countを呼ぶ