File Coverage

blib/lib/Bolts/Meta/Class/Trait/Bag.pm
Criterion Covered Total %
statement 33 44 75.0
branch 12 18 66.6
condition 6 12 50.0
subroutine 28 28 100.0
pod 3 3 100.0
total 82 105 78.1


line stmt bran cond sub pod time code
1             package Bolts::Meta::Class::Trait::Bag;
2             $Bolts::Meta::Class::Trait::Bag::VERSION = '0.143171';
3             # ABSTRACT: Metaclass role for Bolts-built bags
4              
5 11     53   5945 use Moose::Role;
  11         20  
  11         79  
6              
7 11     53   44194 use Safe::Isa;
  11         19  
  11         1377  
8 11     53   57 use Scalar::Util qw( reftype );
  11         12  
  11         5014  
9              
10              
11             has artifacts => (
12             is => 'ro',
13             required => 1,
14             default => sub { +{} },
15             traits => [ 'Hash' ],
16             handles => {
17             '_add_artifact' => 'set',
18             'list_artifacts' => 'elements',
19             },
20             );
21              
22              
23             has such_that_isa => (
24             is => 'rw',
25             isa => 'Moose::Meta::TypeConstraint',
26             predicate => 'has_such_that_isa',
27             );
28              
29              
30             has such_that_does => (
31             is => 'rw',
32             isa => 'Moose::Meta::TypeConstraint',
33             predicate => 'has_such_that_does',
34             );
35              
36              
37             sub is_finished_bag {
38 53     53 1 704 my $meta = shift;
39 53         231 return $meta->is_immutable;
40             }
41              
42              
43             sub add_artifact {
44 216     216 1 401 my ($meta, $name, $value, $such_that) = @_;
45            
46 216 100 100     8230 if (!defined $such_that and ($meta->has_such_that_isa
      33        
47             or $meta->has_such_that_does)) {
48 167         236 $such_that = {};
49 167 100       5322 $such_that->{isa} = $meta->such_that_isa
50             if $meta->has_such_that_isa;
51 167 100       5354 $such_that->{does} = $meta->such_that_does
52             if $meta->has_such_that_does;
53             }
54              
55 216 100 66     639 if ($value->$_does('Bolts::Role::Artifact')) {
    100          
56 214 100       12920 $value->such_that($such_that) if $such_that;
57 214         8012 $meta->_add_artifact($name => $value);
58 214     993   1209 $meta->add_method($name => sub { $value });
  993     993   2476  
        993      
        247      
        1211      
        993      
        1774      
        1384      
        247      
        1289      
        2459      
        1903      
        1921      
        1060      
        18      
        18      
59             }
60              
61             elsif (defined reftype($value) and reftype($value) eq 'CODE') {
62 1         38 my $thunk = Bolts::Artifact::Thunk->new(
63             %$such_that,
64             thunk => $value,
65             );
66              
67 1         37 $meta->_add_artifact($name => $thunk);
68 1     954   6 $meta->add_method($name => sub { $thunk });
  2         4  
69             }
70              
71             else {
72             # TODO It would be better to assert the validity of the checks on
73             # the value immediately.
74              
75             my $thunk = Bolts::Artifact::Thunk->new(
76             %$such_that,
77 2     914   9 thunk => sub { $value },
78 1         52 );
79              
80 1         41 $meta->_add_artifact($name => $thunk);
81 1     601   6 $meta->add_method($name => sub { $thunk });
  2         5  
82             }
83              
84             }
85              
86              
87             sub finish_bag {
88 24     547 1 301 my ($meta) = @_;
89              
90 24         184 $meta->make_immutable(
91             replace_constructor => 1,
92             replace_destructor => 1,
93             );
94              
95 24         146199 return $meta;
96             }
97              
98             sub _wrap_method_in_such_that_check {
99 0     521     my ($meta, $code, $such_that) = @_;
100              
101 0           my $wrapped;
102 0 0 0       if (defined $such_that->{isa} or defined $such_that->{does}) {
103             $wrapped = sub {
104 0     521     my $result = $code->(@_);
105              
106 0 0         $such_that->{isa}->assert_valid($result)
107             if defined $such_that->{isa};
108              
109 0 0         $such_that->{does}->assert_valid($result)
110             if defined $such_that->{does};
111              
112 0           return $result;
113 0           };
114             }
115             else {
116             $wrapped = sub {
117 0     521     return scalar $code->(@_);
118 0           };
119             }
120              
121 0           return $wrapped;
122             }
123              
124              
125             1;
126              
127             __END__
128              
129             =pod
130              
131             =encoding UTF-8
132              
133             =head1 NAME
134              
135             Bolts::Meta::Class::Trait::Bag - Metaclass role for Bolts-built bags
136              
137             =head1 VERSION
138              
139             version 0.143171
140              
141             =head1 DESCRIPTION
142              
143             While a bag may be any kind of object, this metaclass role on a bag provides some helpful utilities for creating and managing bags.
144              
145             =head1 ATTRIBUTES
146              
147             =head2 artifacts
148              
149             These are the artifacts that have been added to this bag. It is saved as a hash. You can get the hash of artifacts as a list using C<list_artifacts>. You add artifacts to this list using L</add_artifact>.
150              
151             =head2 such_that_isa
152              
153             This is a L<Moose::Meta::TypeConstraint> to apply to the L<Bolts::Artifact/isa_type> of all contained artifacts.
154              
155             =head2 such_that_does
156              
157             This is a L<Moose::Meta::TypeConstraint> to apply to the L<Bolts::Artifact/does_type> of all contained artifacts.
158              
159             =head1 METHODS
160              
161             =head2 is_finished_bag
162              
163             my $finished = $meta->is_finished_bag;
164              
165             This is used to determine if a bag's definition has already been performed and completed. At this time, it's just a synonym for L<Class::MOP::Class/is_immutable>.
166              
167             =head2 add_artifact
168              
169             $meta->add_artifact(name => $artifact, {
170             isa => $isa_type,
171             does => $does_type,
172             });
173              
174             Adds an artifact method to the bag with the given C<name>. The C<$artifact> may be an instance of L<Bolts::Role::Artifact>, a code reference to used to define a L<Bolts::Artifact::Thunk> or just another value, which will be wrapped in an anonymous sub and turned into a L<Bolts::Artifact::Thunk>.
175              
176             The C<isa> and C<does> will be applied to the artifact as appropriate.
177              
178             =head2 finish_bag
179              
180             $meta->finish_bag;
181              
182             This completes the bag building process and marks the Moose object as immutable. Aft this is called, L</is_finished_bag> returns true.
183              
184             =head1 AUTHOR
185              
186             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
187              
188             =head1 COPYRIGHT AND LICENSE
189              
190             This software is copyright (c) 2014 by Qubling Software LLC.
191              
192             This is free software; you can redistribute it and/or modify it under
193             the same terms as the Perl 5 programming language system itself.
194              
195             =cut