sequences

Sequences

A sequence is a named counter that yields a new value on every call. Use sequences when you want unique attribute values across factory builds — emails, login names, slugs.

Global sequences

Declare with .sequence inside a define block; consume with ORM::Factory.generate:

define {
  .sequence: 'email', -> $n { "user{$n}\@example.com" };
};

ORM::Factory.generate('email');                 # '[email protected]'
ORM::Factory.generate('email');                 # '[email protected]'
ORM::Factory.generate-list('email', 3);         # the next three values

Without a block, a sequence returns its raw counter:

define { .sequence: 'count'; };
ORM::Factory.generate('count');                 # 1
ORM::Factory.generate('count');                 # 2

Custom start value

:start controls the first value. Numeric starts increment with + 1; string starts advance with .succ:

define {
  .sequence: 'id',     :start(1000);
  .sequence: 'letter', :start('a');
};

ORM::Factory.generate('id');                    # 1000
ORM::Factory.generate('id');                    # 1001

ORM::Factory.generate('letter');                # 'a'
ORM::Factory.generate('letter');                # 'b'

Custom iterator

If a + 1 / .succ progression isn't enough, pass any Iterator and the sequence pulls from it (with an optional block to transform each value):

define {
  .sequence: 'fib', :iterator((1, 1, *+* ... *).iterator);
};

ORM::Factory.generate-list('fib', 5);           # (1, 1, 2, 3, 5)

The sequence raises X::ORM::Factory::UsageError if the iterator is exhausted.

Inline sequences (per-factory)

Declared inside a factory body, a sequence is bound as an attribute on that factory and advances on every build:

define {
  .factory: 'invitation', :class(Invitation), {
    .sequence: 'token', -> $n { "tok-$n" };
  };
};

ORM::Factory.attributes-for('invitation')<token>;   # 'tok-1'
ORM::Factory.attributes-for('invitation')<token>;   # 'tok-2'

Inline sequences are isolated per factory; they have no name in the global sequence registry.

Resetting counters

ORM::Factory.rewind-sequences resets every global sequence's counter back to its :start. It is the standard between-tests cleanup for any spec that asserts on sequence values:

before-each {
  ORM::Factory.rewind-sequences;
}

reload also clears the sequence registry along with factory definitions and aliases.

Errors

ExceptionTrigger
X::ORM::Factory::UnknownSequencegenerate on an unregistered name.
X::ORM::Factory::DuplicateSequenceTwo .sequence 'x', … calls with the same name.
X::ORM::Factory::UsageErrorCustom iterator exhausted.

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.