use strict;
use warnings;
+require 5.00601;
+
use Module::Build;
my $builder = Module::Build->new
- Moose was missing from the prereq list. Reported by Slaven Rezic.
+- Version 0.01 did not work after a class was made immutable.
+
0.01 2007-11-14
Changes
lib/MooseX/Object/StrictConstructor.pm
lib/MooseX/StrictConstructor.pm
+lib/MooseX/StrictConstructor/Meta/Class.pm
+lib/MooseX/StrictConstructor/Meta/Method/Constructor.pm
Makefile.PL
MANIFEST This list of files
META.yml
use Carp 'confess';
+use metaclass 'MooseX::StrictConstructor::Meta::Class';
+
+
extends 'Moose::Object';
after 'BUILDALL' => sub
use strict;
use warnings;
-our $VERSION = '0.01';
+our $VERSION = '0.02';
use Moose;
use MooseX::Object::StrictConstructor;
return if $caller eq 'main';
- Moose::init_meta( $caller, 'MooseX::Object::StrictConstructor', 'Moose::Meta::Class' );
+ Moose::init_meta( $caller,
+ 'MooseX::Object::StrictConstructor',
+ 'MooseX::StrictConstructor::Meta::Class',
+ );
Moose->import( { into => $caller } );
}
}
+=head2 Caveats
+
+Using this class replaces the default Moose meta class,
+C<Moose::Meta::Class>, with its own,
+C<MooseX::StrictConstructor::Meta::Class>. If you have your own meta
+class, this distro will probably not work for you.
+
=head1 AUTHOR
Dave Rolsky, C<< <autarch@urth.org> >>
--- /dev/null
+package MooseX::StrictConstructor::Meta::Class;
+
+use strict;
+use warnings;
+
+use base 'Moose::Meta::Class';
+
+use MooseX::StrictConstructor::Meta::Method::Constructor;
+
+
+sub make_immutable { ## no critic RequireArgUnpacking
+ my $self = shift;
+
+ return
+ $self->SUPER::make_immutable
+ ( constructor_class => 'MooseX::StrictConstructor::Meta::Method::Constructor',
+ @_
+ );
+}
+
+
+1;
--- /dev/null
+package MooseX::StrictConstructor::Meta::Method::Constructor;
+
+use strict;
+use warnings;
+
+use Moose;
+
+extends 'Moose::Meta::Method::Constructor';
+
+sub _generate_BUILDALL ## no critic RequireArgUnpacking
+{
+ my $self = shift;
+
+ my $calls = $self->SUPER::_generate_BUILDALL(@_);
+
+ $calls .= <<'EOF';
+ my %attrs = map { $_->name() => 1 } $self->meta()->compute_all_applicable_attributes();
+
+ my @bad = sort grep { ! $attrs{$_} } keys %params;
+
+ if (@bad)
+ {
+ confess "Found unknown attribute(s) passed to the constructor: @bad";
+ }
+EOF
+
+ return $calls;
+};
+
+
+1;
use strict;
use warnings;
-use Test::More tests => 7;
+use Test::More tests => 9;
{
__PACKAGE__->meta()->make_immutable();
}
+{
+ package ImmutableTricky;
+
+ use MooseX::StrictConstructor;
+
+ has 'thing' => ( is => 'rw' );
+
+ sub BUILD
+ {
+ my $self = shift;
+ my $params = shift;
+
+ delete $params->{spy};
+ }
+}
+
eval { Standard->new( thing => 1, bad => 99 ) };
is( $@, '', 'standard Moose class ignores unknown params' );
eval { Immutable->new( thing => 1, bad => 99 ) };
like( $@, qr/unknown attribute.+: bad/,
'strict constructor in immutable class blows up on unknown params' );
+
+eval { ImmutableTricky->new( thing => 1, spy => 99 ) };
+is( $@, '',
+ 'immutable class can work around strict constructor by deleting params in BUILD()' );
+
+eval { ImmutableTricky->new( thing => 1, agent => 99 ) };
+like( $@, qr/unknown attribute.+: agent/,
+ 'ImmutableTricky still blows up on unknown params other than spy' );