Custom strategies
ORM::Factory ships with four built-in strategies (build, create,
attributes-for, build-stubbed). You can register your own at runtime —
or replace a built-in — to integrate serialisation, alternative persistence
flows, or any other build pipeline.
Registering a strategy
A strategy is any class that does the ORM::Factory::Strategy role:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | use ORM::Factory;
class JsonStrategy does ORM::Factory::Strategy {
method to-sym(--> Str) { 'json' }
method result(ORM::Factory::Evaluator $eval) {
my %h = $eval.attributes-hash(:skip-associations);
to-json(%h);
}
method association(Str:D $name, @variants, %overrides) {
ORM::Factory.build($name, |@variants, |%overrides);
}
}
ORM::Factory.register-strategy('json', JsonStrategy);
|
Once registered, the strategy is dispatched by name via FALLBACK, so the
top-level helper is simply the name itself:
| ORM::Factory.json('user'); # → JSON for the user factory
ORM::Factory.json('user', 'admin', :name<Pat>); # variants + overrides flow through
|
Inspecting the registry
| ORM::Factory.strategies.keys; # registered names
ORM::Factory.strategy-class-for('json'); # the class
ORM::Factory.strategy-for('json'); # a fresh, persistence-wired instance
|
Re-registering a built-in
register-strategy accepts any built-in name, so a project can swap the
default build behaviour without monkey-patching:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | class ShoutBuildStrategy does ORM::Factory::Strategy {
method to-sym(--> Str) { 'build' }
method result(ORM::Factory::Evaluator $eval) {
my $instance = $!persistence.instantiate($eval.factory.lookup-class, $eval.attributes-hash);
$instance.name = $instance.name.uc if $instance.^can('name');
$instance;
}
method association(Str:D $name, @variants, %overrides) {
ORM::Factory.build($name, |@variants, |%overrides);
}
}
ORM::Factory.register-strategy('build', ShoutBuildStrategy);
ORM::Factory.build('user').name; # → uppercased
# Restore the default
ORM::Factory.register-strategy('build', ORM::Factory::BuildStrategy);
|
Per-strategy association cascade
association is the cascade hook. A strategy controls how every implicit or
explicit association of the in-flight factory is built. For example, a
strategy that always stubs associations regardless of the top-level call:
1
2
3
4
5
6
7
8
9
10
11
12 | class StubAssocStrategy does ORM::Factory::Strategy {
method to-sym(--> Str) { 'cascade-stub' }
method result(ORM::Factory::Evaluator $eval) {
$!persistence.instantiate($eval.factory.lookup-class, $eval.attributes-hash);
}
method association(Str:D $name, @variants, %overrides) {
ORM::Factory.build-stubbed($name, |@variants, |%overrides);
}
}
ORM::Factory.register-strategy('cascade-stub', StubAssocStrategy);
ORM::Factory.cascade-stub('article'); # article's author is stubbed
|