99803d2df03504e4cbb47ad9f686ad822b14aeb0
[gitmo/MooseX-StrictConstructor.git] / lib / MooseX / StrictConstructor / Trait / Class.pm
1 package MooseX::StrictConstructor::Trait::Class;
2
3 use Moose::Role;
4
5 use namespace::autoclean;
6
7 use B ();
8
9 around new_object => sub {
10     my $orig = shift;
11     my $self = shift;
12     my $params = @_ == 1 ? $_[0] : {@_};
13     my $instance = $self->$orig(@_);
14
15     my %attrs = (
16         __INSTANCE__ => 1,
17         (map { $_ => 1 }
18              grep { defined }
19                   map { $_->init_arg }
20                       $self->get_all_attributes)
21     );
22
23     my @bad = sort grep { !$attrs{$_} } keys %$params;
24
25     if (@bad) {
26         $self->throw_error(
27             "Found unknown attribute(s) init_arg passed to the constructor: @bad");
28     }
29
30     return $instance;
31 };
32
33 around '_inline_BUILDALL' => sub {
34     my $orig = shift;
35     my $self = shift;
36
37     my @source = $self->$orig();
38
39     my @attrs = (
40         '__INSTANCE__ => 1,',
41         map { B::perlstring($_) . ' => 1,' }
42         grep {defined}
43         map  { $_->init_arg() } $self->get_all_attributes()
44     );
45
46     return (
47         @source,
48         'my %attrs = (' . ( join ' ', @attrs ) . ');',
49         'my @bad = sort grep { !$attrs{$_} } keys %{ $params };',
50         'if (@bad) {',
51             'Moose->throw_error("Found unknown attribute(s) passed to the constructor: @bad");',
52         '}',
53     );
54 } if $Moose::VERSION >= 1.9900;
55
56 1;
57
58 # ABSTRACT: A role to make immutable constructors strict
59
60 __END__
61
62 =pod
63
64 =head1 DESCRIPTION
65
66 This role simply wraps C<_inline_BUILDALL()> (from
67 C<Moose::Meta::Class>) so that immutable classes have a
68 strict constructor.
69
70 =cut