Railsのhas_manyにおけるsize, count, lengthの違い
掲示板アプリみたいなのを想像する。投稿をPostとしてそれにCommentを複数つけられるシンプルなものだ。Post:Commentが1:Nの関係だ。
環境
p = Post.first
#count
[2] pry(main)> p.comments.count (0.3ms) SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id` = 1 => 1 [3] pry(main)> p.comments.count (0.5ms) SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id` = 1 => 1
常にSQLでCOUNT文を流してる。
#size
commentsがロードされている場合、そのcommentsのsizeを返す
[14] pry(main)> p.comments Comment Load (0.4ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`post_id` = 1 [15] pry(main)> p.comments.size => 1
commentsがロードされてない場合、countと同じ
[4] pry(main)> p.comments.size (0.3ms) SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id` = 1 => 1 [5] pry(main)> p.comments.size (0.3ms) SELECT COUNT(*) FROM `comments` WHERE `comments`.`post_id` = 1 => 1
※ 0件の場合は、p.comments.sizeを呼ぶと、その時点でロードされたことになって二度目からはキャッシュされた値を使うので注意。
#length
commentsがロードされている場合、そのcommentsのsizeを返す
[20] pry(main)> p.comments.length => 1
commentsがロードされていない場合、commentsをロードしてそのsizeを返す
[18] pry(main)> p.comments.length Comment Load (0.3ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`post_id` = 1 => 1
まとめ
常にCOUNT文による件数が欲しい場合は、#countを使う。それ以外は、#sizeでOK。#lengthはまぁ使うことはあまりなさそうかな。