File Coverage

blib/lib/MooseX/SlurpyConstructor/Trait/Class.pm
Criterion Covered Total %
statement 10 10 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 14 100.0


line stmt bran cond sub pod time code
1             package MooseX::SlurpyConstructor::Trait::Class;
2             BEGIN {
3 7     7   169 $MooseX::SlurpyConstructor::Trait::Class::VERSION = '1.2';
4             }
5              
6             # applied as class_metaroles => { class => [ __PACKAGE__ ] }.
7              
8 7     7   41 use Moose::Role;
  7         14  
  7         54  
9              
10 7     7   46490 use namespace::autoclean;
  7         17  
  7         63  
11              
12 7     7   527 use B ();
  7         15  
  7         3727  
13              
14             around '_inline_BUILDALL' => sub {
15             my $orig = shift;
16             my $self = shift;
17              
18             my @source = $self->$orig();
19              
20             my @attrs = (
21             '__INSTANCE__ => 1,',
22             map { B::perlstring($_) . ' => 1,' }
23             grep { defined }
24             map { $_->init_arg } $self->get_all_attributes
25             );
26              
27             my $slurpy_attr = $self->slurpy_attr;
28              
29             return (
30             @source,
31             'my %attrs = (' . ( join ' ', @attrs ) . ');',
32             'my @extra = sort grep { !$attrs{$_} } keys %{ $params };',
33             'if (@extra){',
34              
35             !$slurpy_attr
36             ? 'Moose->throw_error("Found extra construction arguments, but there is no \'slurpy\' attribute present!");'
37             : (
38             'my %slurpy_values;',
39             '@slurpy_values{@extra} = @{$params}{@extra};',
40              
41             '$instance->meta->slurpy_attr->set_value( $instance, \%slurpy_values );',
42             ),
43             '}',
44             );
45             }
46             if Moose->VERSION >= 1.9900;
47              
48             # quick access to the slurpy attribute
49             # (which holds the extra constructor arguments)
50             has slurpy_attr => (
51             is => 'rw',
52             isa => 'Maybe[Moose::Meta::Attribute]',
53             weak_ref => 1,
54             );
55              
56             # stores the location of the slurpy attribute; reader also looks up the class
57             # heirarchy
58             around slurpy_attr => sub {
59             my $orig = shift;
60             my $self = shift;
61              
62             # writer
63             return $self->$orig(@_) if @_;
64              
65             # reader
66              
67             my $result = $self->$orig;
68             return $result if $result;
69              
70             # we need to walk the inheritance tree, checking all metaclasses for
71             # the one that holds a slurpy_attr with a defined value.
72             my @slurpy_attr_values = map {
73             my $attr = $_->meta->meta->get_attribute('slurpy_attr');
74             !$attr
75             ? ()
76             : $attr->get_value($_->meta) || ();
77             }
78             $self->linearized_isa;
79              
80             foreach my $ancestor ($self->linearized_isa)
81             {
82             my $attr = $ancestor->meta->meta->find_attribute_by_name('slurpy_attr');
83             next if not $attr;
84             my $attr_value = $attr->get_value($ancestor->meta);
85             return $attr_value if $attr_value;
86             }
87              
88             # no slurpy_attrs found
89             return;
90             };
91              
92             # if the Object role is applied first, and then a superclass added, we just
93             # lost our BUILDALL modification.
94             after superclasses => sub
95             {
96             my $self = shift;
97             return if not @_;
98             Moose::Util::MetaRole::apply_base_class_roles(
99             for => $self->name,
100             roles => ['MooseX::SlurpyConstructor::Role::Object'],
101             )
102             };
103              
104             1;
105              
106             # ABSTRACT: A role to make immutable constructors slurpy, and add meta-information used to find slurpy attributes
107              
108              
109              
110             =pod
111              
112             =head1 NAME
113              
114             MooseX::SlurpyConstructor::Trait::Class - A role to make immutable constructors slurpy, and add meta-information used to find slurpy attributes
115              
116             =head1 VERSION
117              
118             version 1.2
119              
120             =head1 DESCRIPTION
121              
122             This role simply wraps C<_inline_BUILDALL()> (from
123             C<Moose::Meta::Class>) so that immutable classes have a
124             slurpy constructor.
125              
126             =head1 AUTHORS
127              
128             =over 4
129              
130             =item *
131              
132             Mark Morgan <makk384@gmail.com>
133              
134             =item *
135              
136             Karen Etheridge <ether@cpan.org>
137              
138             =back
139              
140             =head1 COPYRIGHT AND LICENSE
141              
142             This software is copyright (c) 2011 by Karen Etheridge.
143              
144             This is free software; you can redistribute it and/or modify it under
145             the same terms as the Perl 5 programming language system itself.
146              
147             =cut
148              
149              
150             __END__
151