Changes

  • -TLDR
  • -------
  • -- When counting records in an association, you should **use `#size` in most cases.**
  • -- It will not work if the parent record has never been saved. Also there are finer distinctions between `#size` and `#count`. See below.
  • +**TL;DR:** You should generally use `#size` to count associated records.
  • -## count
  • -- Always makes a `COUNT(*)` query if a counter cache is not set up.
  • -- If a counter cache is set up on the association, `#count` will return that cached value instead of executing a new query.
  • +## size
  • +- Counts already loaded elements
  • +- If the association is not loaded, falls back to a `COUNT` query
  • -## size, if the association has already been loaded
  • -- Counts elements in the already loaded array.
  • -- Does not make another query.
  • +## count
  • +- If a counter cache is set up, returns the cached value
  • +- Will issue a `COUNT` query else
  • -## size, if the association has not yet been loaded
  • -- Makes a `COUNT(*)` query, just like `#count`
  • +### Caveats
  • +- If you trigger a `COUNT` query for an unsaved record, Rails will try to load all children where the foreign key `IS NULL`. This is not what you want. To prevent this behavior, you can use `association.to_a.size`.
  • +- `count` looks directly into the database, **neglecting already loaded elements**. E.g. in tests, an intermediate `expect(record.association.count).to eq 1` to assert a precondition may be green. However, the association may still have already been loaded as empty `[]`, so your assertion is void. In this example, `record.association.size` would be correct.
  • ## length
  • -- Always loads the contents of the association into memory, then returns the number of elements loaded.
  • -
  • -
  • -## Caveat for unsaved records
  • -- If you trigger a `COUNT(*)` by whatever means, Rails will try to load all children where the foreign key `IS NULL`. This is not what you want, ever.
  • -- If you want to count children and not fall into this trap, use `association.to_a.size`.
  • +- Fetches the records from the database, then returns the number of elements
  • +None of these methods actually loads the association, i.e. `record.association(:association_name).loaded?` will not change.
Dominik Schöler
Last edit
Dominik Schöler
License
Source code in this card is licensed under the MIT License.
Posted by Dominik Schöler to makandra dev (2024-05-07 12:42)