ActiveRecord の size メソッドの落とし穴

size メソッドは、count メソッドと length メソッドのいいとこどりのメソッドです。

  • 既にデータがロードされていれば、それを使う
  • sql 発行されない
  • データがロードされていなければ、select count(*) from ... を発行する

なので多用していたのですが、このたび一つ失敗しました。

例えば User モデルに紐付いた Invitation モデルがあるとします。

invitation = current_user.invitations.build
current_user.invitations.size    # => 1
current_user.invitations.length # => 1
current_user.invitations.count  # => 0

関連の build メソッドで Invitation を増やすと、DB に入っていない状態にもかかわらず一つ増えた扱いになるのです。length も一緒。なので DB に入っている関連の数を取得したい場合は、count を使うのが良いですね。

追記

build で関連を増やすとその後の状態に影響するの、Rails 4.0 からっぽいです