Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Create a "setup" attribute trait that works kinda like default, but h…

…appens at BUILD time. Works around initializer, builder and default constraints.
  • Loading branch information...
commit 352e4d9166715a7ee29ddd9bdedb8391ee73f647 1 parent e56160c
@rcaputo authored
View
27 docs/EmitterTrait.pm
@@ -42,6 +42,28 @@ has trigger => (
}
);
+has initializer => (
+ is => 'ro',
+ default => sub {
+ my $role;
+ return sub {
+ my ($self, $value, $callback, $attr) = @_;
+ my $event;
+ $self->emit(
+ args => {
+ value => $value,
+ },
+ event => (
+ $event ||=
+ $self->meta->find_attribute_by_name($attr->name())->event()
+ ),
+ );
+
+ $callback->($value);
+ }
+ },
+);
+
has event => (
isa => 'Str',
is => 'ro',
@@ -51,6 +73,11 @@ has event => (
},
);
+has setup => (
+ isa => 'CodeRef',
+ is => 'ro',
+);
+
package Moose::Meta::Attribute::Custom::Trait::Emitter;
sub register_implementation { 'EmitterTrait' }
View
47 docs/ObserverTrait.pm
@@ -34,6 +34,32 @@ has trigger => (
}
);
+# Initializer seems to catch the observation from default. Nifty!
+
+has initializer => (
+ is => 'ro',
+ default => sub {
+ my $role;
+ return sub {
+ my ($self, $value, $callback, $attr) = @_;
+ if (defined $value) {
+ $self->observe_role(
+ observed => $value,
+ role => (
+ $role ||=
+ $self->meta->find_attribute_by_name($attr->name())->role()
+ ),
+ );
+ }
+ else {
+ # TODO - Ignore the object in the old value, if defined.
+ }
+
+ $callback->($value);
+ }
+ },
+);
+
has role => (
isa => 'Str',
is => 'ro',
@@ -43,6 +69,27 @@ has role => (
},
);
+has setup => (
+ isa => 'CodeRef',
+ is => 'ro',
+);
+
+# TODO - Clearers don't invoke triggers, because clearing is different
+# from setting. I would love to support $self->clear_thingy() with
+# the side-effect of unobserving the object, but I don't yet know how
+# to set an "after" method for a clearer that (a) has a dynamic name,
+# and (b) hasn't yet been defined. I think I can do some meta magic
+# for (a), but (b) remains tough.
+
+#has clearer => (
+# isa => 'Str',
+# is => 'ro',
+# default => sub {
+# my $self = shift;
+# return "clear_" . $self->name();
+# },
+#);
+
package Moose::Meta::Attribute::Custom::Trait::Observer;
sub register_implementation { 'ObserverTrait' }
View
18 docs/StageRole.pm
@@ -157,6 +157,17 @@ has observers => (
sub BUILD {
my ($self, $args) = @_;
+ foreach my $setup (
+ (grep { $_->does('Emitter') } $self->meta()->get_all_attributes()),
+ (grep { $_->does('Observer') } $self->meta()->get_all_attributes())
+ ) {
+ my $callback = $setup->setup();
+ if (defined $callback) {
+ my $member = $setup->name();
+ $self->$member( $callback->() ); # TODO - Proper parameters!
+ }
+ }
+
foreach my $observer (@{$self->observers()}) {
# Observing based on role.
@@ -431,7 +442,7 @@ sub _check_args {
# The filehash should destroy everything it observes.
# All observations of this object must be manually demolished.
-sub DEMOLISH {
+sub shutdown {
my $self = shift;
# Anything that was watching us, no longer is.
@@ -453,6 +464,11 @@ sub DEMOLISH {
}
}
+sub DEMOLISH {
+ my $self = shift;
+ $self->shutdown();
+}
+
sub ignore {
my ($self, @args) = @_;
View
53 docs/eg-10-setup.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+
+{
+ package Counter;
+ use Moose;
+ extends 'Stage';
+ use Delay;
+ use ObserverTrait;
+ use EmitterTrait;
+
+ has count => (
+ traits => ['Emitter'],
+ isa => 'Int',
+ is => 'rw',
+ default => 0,
+ );
+
+ has ticker => (
+ traits => ['Observer'],
+ isa => 'Delay',
+ is => 'rw',
+ setup => sub { Delay->new( interval => 1, auto_repeat => 1 ) },
+ );
+
+ sub on_ticker_tick {
+ my $self = shift;
+ $self->count($self->count() + 1);
+ }
+}
+
+{
+ package Watcher;
+ use Moose;
+ extends 'Stage';
+
+ has counter => (
+ traits => ['Observer'],
+ isa => 'Counter|Undef',
+ is => 'rw',
+ setup => sub { Counter->new() },
+ );
+
+ sub on_counter_count {
+ my ($self, $args) = @_;
+ warn "Watcher sees counter count: $args->{value}\n";
+
+ $self->counter(undef) if $args->{value} >= 5;
+ }
+}
+
+my $w = Watcher->new();
+Stage->run_all();
+exit;
Please sign in to comment.
Something went wrong with that request. Please try again.