r.respondents.select(:name).uniq
をオーバーライドする ActiveRecord::Relation オブジェクトを返しますsize
。
参照: http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-size
このようなオブジェクトを呼び出すsize
と、オブジェクトが「ロードされている」かどうかがチェックされます。
# Returns size of the records.
def size
loaded? ? @records.length : count
end
@records
「ロード」されている場合は、配列の長さを返します。それ以外の場合は、 を呼び出しますcount
。これは、引数なしで、 「モデルのすべての行の数を返します」 。
では、なぜこのような振る舞いをするのでしょうか? to_a
AR::Relation は、またはexplain
が最初に呼び出された場合にのみ「ロード」されます。
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation.rb
その理由は、load
メソッドの上のコメントで説明されています。
# Causes the records to be loaded from the database if they have not
# been loaded already. You can use this if for some reason you need
# to explicitly load some records before actually using them. The
# return value is the relation itself, not the records.
#
# Post.where(published: true).load # => #<ActiveRecord::Relation>
def load
unless loaded?
# We monitor here the entire execution rather than individual SELECTs
# because from the point of view of the user fetching the records of a
# relation is a single unit of work. You want to know if this call takes
# too long, not if the individual queries take too long.
#
# It could be the case that none of the queries involved surpass the
# threshold, and at the same time the sum of them all does. The user
# should get a query plan logged in that case.
logging_query_plan { exec_queries }
end
self
end
したがって、おそらく使用AR::Relation#size
は、このリレーションに対するクエリの潜在的な複雑さのサイズの尺度でありlength
、返されたレコードの数にフォールバックします。