Dependent attributes

An attribute defined as a block can reference any other attribute on the factory by calling it as a method on the evaluator. The evaluator is bound to $_ inside the block, so the dot-syntax stays terse.

Referencing another attribute#

define {
  .factory: 'user', {
    .fname: 'Greg';
    .email: { .fname.lc ~ '@example.com' };
  };
};

ORM::Factory.build('user').email;   # 'greg@example.com'

.fname inside the email block reads $_.fname on the evaluator, which returns the resolved value (after caching).

Declaration order is preserved#

The order you declare attributes is the order they live on the FactoryDefinition. The evaluator memoises each attribute the first time it is requested, so a downstream attribute that pulls an upstream value sees the cached result regardless of textual order:

define {
  .factory: 'user', {
    .fname:    'Greg';
    .lname:    'Donald';
    .email:    { .fname ~ '@example.com' };
    .nickname: { .fname.lc };
  };
};

ORM::Factory.factory-by-name('user').attributes.map(*.name).list;
# ['fname', 'lname', 'email', 'nickname']

Overrides flow through#

A per-call override is visible to dependent attributes too — the override goes through the same evaluator, so the dependent block sees the override rather than the declared default:

ORM::Factory.build('user', :fname<Alice>).email;   # 'alice@example.com'

See Overrides for the override mechanics in detail.