A little too much help
None of this (short) post is meant to impugn the usefulness of ActiveRecord. But this is a bug waiting to happen. (Or “was”, given that it had me smacking my forehead like a dolt IRL about a month ago.)
In Ruby, Array#length
and Array#count
are generally expected
to behave similarly. (#count
can take a block to filter the total,
but with no arguments, they both tell you how many things are in
the array. Simple enough.) ActiveRecord (mostly) helpfully makes
its non-array return values look like arrays. That is: when you do
this…
records = Model.where(attr: "has_some_value")
…AR consipires to allow records
to work like an array. It is of course actually an instance
of ActiveRecord::Relation
, for reasons having to do with lazy evaluation of SQL queries,
and this is generally pretty badass. Except when ActiveRecord::Relation#count
doesn’t actually
behave like Array#count
:
# how many there are in the db
records.length
=> 20
records.count
=> 20
# but we can add some arbitrary object to this "array"---AR will not complain about this:
records << Object.new
# this shows the updated cardinality of our "array"
records.length
=> 21
# ...but this calls an actual "SELECT COUNT" on the db, so it doesn't understand we added something
records.count
=> 20
Manifestly, this is not the end of the world. But remember not to treat these methods as synonymous when dealing with ActiveRecord.