Help language development. Donate to The Perl Foundation

Red cpan:FCO last updated on 2020-11-22

# Relationships

Relationships in [Red]( are defined by the `is relationship` trait. It should receive (at least) a Str named parameter called `:model`
that represents the related model, a Callable positional parameter that will return one (or more) referencing columns, and it must have a sigil. The sigil can be:

- `$` - Represents a `belongs to` relationship that "stores" only 1 element. [Red]( will run the callable passing the model itself as the only parameter.

- `@` - Represents a `has many` relationship that "stores" a `ResultSeq` of elements. [Red]( will run the callable passing the model
  defined by the `:model` named parameter.

(for the experimental `has-one`, please take a look at [experimental doc](experimental.html))

## So, for example:

# Person.rakumod
use Red:ver<2>;

model Person {
  has UInt $!id    is serial;
  has Str  $.name  is column;
  has      @.books is relationship(*.author-id, :model<Book>);

# Book.rakumod
use Red:ver<2>;

model Book {
  has UInt $!id        is serial;
  has Str  $.name      is column;
  has UInt $!author-id is referencing(*.id, :model<Person>);
  has      $.author    is relationship(*.author-id, :model<Person>);

Book has a foreign key ($!author-id) that references `` (this is defined by the `is referencing` trait). And it also has a relationship ($.author)
that's auto pre-fetched using a `join` based on `book.author_id =`.

Person has no foreign key but it does have a relationship (`@.books`) that isn't pre-fetched because it's a `has many` relationship. So when its value is accessed
a new query is run.

On that example, to create a new book related to (written by) a given person, one could do something like:

my $author = Person.^all.first: *.name eq "Chico Buarque";
$author.books.create: :name<Benjamin>;

As mentioned, `@.books` is a `ResultSeq`, so it accepts any of its methods, eg:

$author.books.grep(*.starts-with: "Ben").elems

For getting the number of books written by "Chico Buarque" that starts with "Ben".