@BelongsTo
, @HasMany
, and @HasOne
.
Consider a database with tables users
, todos
, tags
, todo_tags
.
BelongsTo
is the simplest kind of relationship. It represents the child of a 1-1 or 1-M relationship. The child typically has a column referencing the primary key of another table.
@BelongsTo
property wrapper and types, Rune will infer a user_id
key on Todo and an id
key on users
when eager loading. If the keys differ, for example users
local key is my_id
you may access the RelationshipMapping
in Model.mapRelations
and override either key with to(...)
or from(...)
. to
overrides the key on the destination of the relation, from
overrides the key on the model the relation is on.
id
on users
and a foreign key user_id
on todos
. You can override either using the same mapRelations
function.
HasMany
except it wraps single value, not an array. Overriding keys works the same way.
.through(...)
mapping provides a convenient way to access distant relations via an intermediate relation.
Consider tables representing a CI system user
, projects
, workflows
.
through(...)
function.
.from
& .to
functions and you can override the intermediary table keys with the from
and to
parameters of through
.
.through(...)
mapping can also be applied to a HasOne
relationship. It functions the same, with overrides available for from
, throughFrom
, throughTo
, and to
.
throughPivot
function to define a @HasMany
relationship to function this way.
through
, keys are inferred but you may specify from
and to
parameters to indicate the keys on the pivot table.
Model
, you need to load that relationship first. You can “eager load” it using the .with()
function on a ModelQuery
. Eager loading refers to preemptively, or “eagerly”, loading a relationship before it is used. Eager loading also solves the N+1 problem; if N Pet
s are returned with a query, you won’t need to run N queries to find each of their Owner
s. Instead, a single, followup query will be run that finds all Owner
s for all Pet
s fetched.
This function takes a KeyPath
to a relationship and runs a query to fetch it when the initial query is finished.
Model
using .with()
.
.with()
function takes a KeyPath
to a relationship not a Model
, so be sure to preface your key path with a $
.
Warning 2: If you access a relationship before it’s loaded, the program will fatalError
. Be sure a relationship is loaded with eager loading before accessing it!
Model
s. You can do this with the second, closure argument of with()
.
Consider three relationships, Homework
, Student
, School
. A Homework
belongs to a Student
and a Student
belongs to a School
.
You might represent them in a database like so
Homework
, you can use nested eager loading like so