use Scalar::Util 'weaken', 'reftype';
use Carp 'confess';
-use Moose::Util::TypeConstraints ':no_export';
-
-our $VERSION = '0.01';
+our $VERSION = '0.02';
use base 'Class::MOP::Attribute';
-Moose::Meta::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('weak_ref' => (
- reader => 'weak_ref',
- predicate => {
- 'has_weak_ref' => sub { $_[0]->weak_ref() ? 1 : 0 }
- }
- ))
-);
+__PACKAGE__->meta->add_attribute('coerce' => (reader => 'coerce'));
+__PACKAGE__->meta->add_attribute('weak_ref' => (reader => 'weak_ref'));
+__PACKAGE__->meta->add_attribute('type_constraint' => (
+ reader => 'type_constraint',
+ predicate => 'has_type_constraint',
+));
-Moose::Meta::Attribute->meta->add_attribute(
- Class::MOP::Attribute->new('type_constraint' => (
- reader => 'type_constraint',
- predicate => 'has_type_constraint',
- ))
-);
+sub has_coercion { (shift)->coerce() ? 1 : 0 }
+sub has_weak_ref { (shift)->weak_ref() ? 1 : 0 }
-Moose::Meta::Attribute->meta->add_before_method_modifier('new' => sub {
+__PACKAGE__->meta->add_before_method_modifier('new' => sub {
my (undef, undef, %options) = @_;
- (reftype($options{type_constraint}) && reftype($options{type_constraint}) eq 'CODE')
- || confess "Type cosntraint parameter must be a code-ref, not " . $options{type_constraint}
- if exists $options{type_constraint};
+ if (exists $options{coerce} && $options{coerce}) {
+ (exists $options{type_constraint})
+ || confess "You cannot have coercion without specifying a type constraint";
+ confess "You cannot have a weak reference to a coerced value"
+ if $options{weak_ref};
+ }
});
sub generate_accessor_method {
if ($self->has_weak_ref) {
return sub {
if (scalar(@_) == 2) {
- (defined $self->type_constraint->($_[1]))
- || confess "Attribute ($attr_name) does not pass the type contraint"
+ (defined $self->type_constraint->check($_[1]))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
weaken($_[0]->{$attr_name});
};
}
else {
- return sub {
- if (scalar(@_) == 2) {
- (defined $self->type_constraint->($_[1]))
- || confess "Attribute ($attr_name) does not pass the type contraint"
- if defined $_[1];
- $_[0]->{$attr_name} = $_[1];
- }
- $_[0]->{$attr_name};
- };
+ if ($self->has_coercion) {
+ return sub {
+ if (scalar(@_) == 2) {
+ my $val = $self->type_constraint->coercion->coerce($_[1]);
+ (defined $self->type_constraint->check($val))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$val'"
+ if defined $val;
+ $_[0]->{$attr_name} = $val;
+ }
+ $_[0]->{$attr_name};
+ };
+ }
+ else {
+ return sub {
+ if (scalar(@_) == 2) {
+ (defined $self->type_constraint->check($_[1]))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
+ if defined $_[1];
+ $_[0]->{$attr_name} = $_[1];
+ }
+ $_[0]->{$attr_name};
+ };
+ }
}
}
else {
if ($self->has_type_constraint) {
if ($self->has_weak_ref) {
return sub {
- (defined $self->type_constraint->($_[1]))
- || confess "Attribute ($attr_name) does not pass the type contraint"
+ (defined $self->type_constraint->check($_[1]))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
if defined $_[1];
$_[0]->{$attr_name} = $_[1];
weaken($_[0]->{$attr_name});
};
}
else {
- return sub {
- (defined $self->type_constraint->($_[1]))
- || confess "Attribute ($attr_name) does not pass the type contraint"
- if defined $_[1];
- $_[0]->{$attr_name} = $_[1];
- };
+ if ($self->has_coercion) {
+ return sub {
+ my $val = $self->type_constraint->coercion->coerce($_[1]);
+ (defined $self->type_constraint->check($val))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$val'"
+ if defined $val;
+ $_[0]->{$attr_name} = $val;
+ };
+ }
+ else {
+ return sub {
+ (defined $self->type_constraint->check($_[1]))
+ || confess "Attribute ($attr_name) does not pass the type contraint with '$_[1]'"
+ if defined $_[1];
+ $_[0]->{$attr_name} = $_[1];
+ };
+ }
}
}
else {
=head1 NAME
-Moose::Meta::Attribute -
+Moose::Meta::Attribute - The Moose attribute metaobject
=head1 SYNOPSIS
=head1 DESCRIPTION
+This is a subclass of L<Class::MOP::Attribute> with Moose specific
+extensions.
+
=head1 METHODS
=over 4
=item B<weak_ref>
+=item B<coerce>
+
+=item B<has_coercion>
+
=back
=head1 BUGS
exception. If you find a bug please either email me, or add the bug
to cpan-RT.
-=head1 CODE COVERAGE
-
-I use L<Devel::Cover> to test the code coverage of my tests, below is the
-L<Devel::Cover> report on this module's test suite.
-
-=head1 ACKNOWLEDGEMENTS
-
=head1 AUTHOR
Stevan Little E<lt>stevan@iinteractive.comE<gt>