module Athena::ORM::Collection(T)
#
The type of an entity's AORMA::OneToMany and AORMA::ManyToMany association fields.
Type the property as AORM::Collection(T), where T is the associated entity, and initialize it with an empty AORM::ArrayCollection(T):
@[AORMA::Entity]
class User < AORM::Entity
# ...
@[AORMA::ManyToMany(inversed_by: "users")]
property groups : AORM::Collection(Group) = AORM::ArrayCollection(Group).new
# Keeps both sides of the association in sync in memory.
def add_group(group : Group) : Nil
self.groups << group
group.users << self
end
end
user = User.new
user.add_group Group.new # Works before the user is ever persisted
Warning
The default value is required, since the ORM reads the element type from it.
The ORM swaps the collection for an AORM::PersistentCollection(T):
- When a flush processes the entity, any other collection assigned to the field is replaced by a persistent one holding the same elements.
- When the entity is loaded from the database, the field holds a persistent collection whose elements aren't loaded yet.
They're loaded with a single query the first time the collection is read, see
AORM::PersistentCollection.
So code should only rely on the AORM::Collection(T) API, not on the field holding a specific implementation.
Both implementations are Indexable(T), so the usual Enumerable and Indexable methods are available alongside <<, delete, remove_element, includes? and clear.
Owning and inverse sides#
Only changes to the owning side of an association are written to the database.
Adding an element to, or removing one from, a AORMA::ManyToMany collection without mapped_by inserts or deletes its row in the join table on the next flush.
A AORMA::OneToMany collection is always the inverse side: the foreign key lives on the element's AORMA::ManyToOne field, so set that field for the change to be written.
Changes made only to an inverse side are ignored, so keep both sides in sync, as add_group does above.
New entities added to a collection are only inserted if they're persisted themselves, or the association is mapped with cascade: ["persist"]; otherwise the flush raises.
Once a flush deletes an entity, it's also removed from the loaded collections of managed entities that still contained it.
Direct including types
Athena::ORM::AbstractLazyCollection(T)
Athena::ORM::ArrayCollection(T)