Getting started
This page walks you through defining your first factory, reading it back from the registry, and resetting state between tests.
Install
1 | |
Defining a factory
define opens a definition block. Inside, the topic ($_) is
bound to a DefinitionBuilder, so DSL calls use the leading-dot shorthand:
1 2 3 4 5 6 7 8 9 | |
A static attribute takes any non-Callable value: .fname: 'Greg'. A
dynamic attribute takes a single Callable and is evaluated lazily:
.email: { 'user@example.com' }.
Class inference and overrides
ORM::Factory camelizes the factory name ('user' → User, 'super-admin' →
SuperAdmin, 'team_lead' → TeamLead) and looks the result up in GLOBAL.
A top-level class User { … } in any compunit will be found.
When the camelized name doesn't match your class — or the class lives in a namespace — pass it explicitly:
1 2 3 4 5 | |
To turn off name-based inference entirely (e.g. you only want explicit classes):
1 | |
lookup-class on a FactoryDefinition raises
X::ORM::Factory::UnknownClass if the class can't be resolved and no
override was supplied.
behave EVALs each spec file.
our class Foo { … }declared during EVAL does not land inGLOBALthe way a normal compunit does, so name inference may miss it. In behave specs, either bind explicitly (BEGIN GLOBAL::<Foo> := Foo;) or pass:class(Foo)per factory.
Aliases
A factory can be registered under additional names:
1 2 3 4 5 6 7 8 | |
Aliases collide with both factory names and other aliases — the
duplicate-registration guard raises X::ORM::Factory::DuplicateAlias if you
try to claim a name that's already in use.
Reading the registry
Definitions land in a process-global registry keyed by name:
1 2 3 4 5 6 7 | |
Looking up an unregistered name raises X::ORM::Factory::UnknownFactory.
Variants
A variant is an alternate set of overrides scoped to one factory. Define
one with .variant, apply it inside the same factory body with a bare
leading-dot call:
1 2 3 4 5 6 7 8 9 10 11 | |
The .admin call resolves against the registered variant name first. If the
name isn't a registered variant, it falls back to capturing an attribute
named admin.
Names that collide with the DSL
DSL method names — factory, variant, transient, association,
add-attribute, before, after, initialize-with, to-create, modify,
skip-create — cannot be captured by the FALLBACK shortcut. Use the explicit
add-attribute escape hatch:
1 2 | |
add-attribute skips the FALLBACK indirection and stores exactly what you
pass: a Callable arg is treated as dynamic, anything else as static, with
no chance of colliding with a method name on the builder.
Resetting between tests
ORM::Factory.reload clears the registry. Run it before each test to keep
suites from leaking definitions:
1 2 3 4 5 6 7 8 9 10 | |
For prove6, just call ORM::Factory.reload at the top of each test block.
See Tests for the full convention.
Diagnostics
The library raises typed exceptions under X::ORM::Factory::*:
| Exception | Trigger |
|---|---|
X::ORM::Factory::UnknownFactory |
factory-by-name on an unregistered name. |
X::ORM::Factory::DuplicateFactory |
Two .factory 'x', … calls with the same name. |
X::ORM::Factory::DuplicateVariant |
Two .variant 'x', … calls in the same factory. |
X::ORM::Factory::UsageError |
Argument shape the DSL can't make sense of (e.g. a variant applied with arguments). |