File Coverage

blib/lib/Bread/Board/Types.pm
Criterion Covered Total %
statement 37 37 100.0
branch 8 8 100.0
condition n/a
subroutine 7 7 100.0
pod n/a
total 52 52 100.0


line stmt bran cond sub pod time code
1             package Bread::Board::Types;
2             our $AUTHORITY = 'cpan:STEVAN';
3             # ABSTRACT: types and coercions for Bread::Board
4             $Bread::Board::Types::VERSION = '0.36';
5 63     63   25421 use Moose::Util::TypeConstraints;
  63         14896105  
  63         726  
6              
7 63     63   158488 use Scalar::Util qw(blessed);
  63         165  
  63         4477  
8              
9 63     63   27871 use Bread::Board::Service;
  63         346  
  63         3481  
10 63     63   29737 use Bread::Board::Dependency;
  63         335  
  63         49509  
11              
12             ## for Bread::Board::Container
13              
14             class_type 'Bread::Board::Container';
15             class_type 'Bread::Board::Container::Parameterized';
16              
17             subtype 'Bread::Board::Container::SubContainerList'
18             => as 'HashRef[Bread::Board::Container|Bread::Board::Container::Parameterized]';
19              
20             coerce 'Bread::Board::Container::SubContainerList'
21             => from 'ArrayRef[Bread::Board::Container]'
22             => via { +{ map { $_->name => $_ } @$_ } };
23              
24             subtype 'Bread::Board::Container::ServiceList'
25             => as 'HashRef[Bread::Board::Service]';
26              
27             coerce 'Bread::Board::Container::ServiceList'
28             => from 'ArrayRef[Bread::Board::Service]'
29             => via { +{ map { $_->name => $_ } @$_ } };
30              
31             ## for Bread::Board::Service::WithDependencies ...
32              
33             subtype 'Bread::Board::Service::Dependencies'
34             => as 'HashRef[Bread::Board::Dependency]';
35              
36             my $ANON_INDEX = 1;
37             sub _coerce_to_dependency {
38 103     103   298 my ($dep) = @_;
39              
40 103 100       640 if (!blessed($dep)) {
41 35 100       166 if (ref $dep eq 'HASH') {
    100          
42 1         5 my ($service_path) = keys %$dep;
43 1         4 my ($service_params) = values %$dep;
44 1         42 $dep = Bread::Board::Dependency->new(
45             service_path => $service_path,
46             service_params => $service_params
47             );
48             }
49             elsif (ref $dep eq 'ARRAY') {
50 3         484 require Bread::Board::BlockInjection;
51 3         20 my $name = '_ANON_COERCE_' . $ANON_INDEX++ . '_';
52 3         12 my @deps = map { _coerce_to_dependency($_) } @$dep;
  9         42  
53 3         17 my @dep_names = map { "${name}DEP_$_" } 0..$#deps;
  9         50  
54             $dep = Bread::Board::Dependency->new(
55             service_name => $name,
56             service => Bread::Board::BlockInjection->new(
57             name => $name,
58 9         197 dependencies => { map { $dep_names[$_] => $deps[$_]->[1] }
59             0..$#deps },
60             block => sub {
61 3     3   11 my ($s) = @_;
62 3         13 return [ map { $s->param($_) } @dep_names ];
  9         40  
63             },
64 3         16 ),
65             );
66 3         137 $dep->service->parent($dep);
67             }
68             else {
69 31         1301 $dep = Bread::Board::Dependency->new(service_path => $dep);
70             }
71             }
72              
73 103 100       1274 if ($dep->isa('Bread::Board::Dependency')) {
74 50         1956 return [$dep->service_name => $dep];
75             }
76             else {
77 53         2005 return [$dep->name => Bread::Board::Dependency->new(service => $dep)];
78             }
79             }
80              
81             coerce 'Bread::Board::Service::Dependencies'
82             => from 'HashRef[Bread::Board::Service | Bread::Board::Dependency | Str | HashRef | ArrayRef]'
83             => via {
84             +{
85             map { $_ => _coerce_to_dependency($_[0]->{$_})->[1] }
86             keys %{$_[0]}
87             }
88             }
89             => from 'ArrayRef[Bread::Board::Service | Bread::Board::Dependency | Str | HashRef]'
90             => via {
91             +{
92             map { @{ _coerce_to_dependency($_) } } @{$_[0]}
93             }
94             };
95              
96             ## for Bread::Board::Service::WithParameters ...
97              
98             subtype 'Bread::Board::Service::Parameters' => as 'HashRef';
99              
100             coerce 'Bread::Board::Service::Parameters'
101             => from 'ArrayRef'
102             => via { +{ map { $_ => { optional => 0 } } @$_ } };
103              
104 63     63   742 no Moose::Util::TypeConstraints; 1;
  63         199  
  63         724  
105              
106             __END__
107              
108             =pod
109              
110             =encoding UTF-8
111              
112             =head1 NAME
113              
114             Bread::Board::Types - types and coercions for Bread::Board
115              
116             =head1 VERSION
117              
118             version 0.36
119              
120             =head1 DESCRIPTION
121              
122             This package defines types and coercions for L<Bread::Board>.
123              
124             =head1 TYPES
125              
126             =head2 C<Bread::Board::Container::SubContainerList>
127              
128             A hashref mapping strings to instances of L<Bread::Board::Container>
129             or L<Bread::Board::Container::Parameterized>.
130              
131             Can be coerced from an arrayref of containers: the keys will be the
132             containers' names.
133              
134             =head2 C<Bread::Board::Container::ServiceList>
135              
136             A hashref mapping strings to instances of L<Bread::Board::Service>.
137              
138             Can be coerced from an arrayref of services: the keys will be the
139             services' names.
140              
141             =head2 C<Bread::Board::Service::Dependencies>
142              
143             Hashref mapping strings to instances of L<Bread::Board::Dependency>.
144              
145             The values of the hashref can be coerced in several different ways:
146              
147             =over 4
148              
149             =item a string
150              
151             will be interpreted as the L<< C<service_path>|Bread::Board::Dependency/service_path >>
152              
153             =item a hashref with a single key
154              
155             the key will be interpreted as a L<<
156             C<service_path>|Bread::Board::Dependency/service_path >>, and the
157             value as a hashref for L<<
158             C<service_params>|Bread::Board::Dependency/service_params >>
159              
160             =item an arrayref
161              
162             each element will be interpreted as a dependency (possibly through all
163             the coercions listed here); see below for an example
164              
165             =item a L<service|Bread::Board::Service> object
166              
167             will be interpreted as a dependency on that service
168              
169             =item a L<dependency|Bread::Board::Dependency> object
170              
171             will be taken as-is
172              
173             =back
174              
175             Instead of a hashref of any of the above things, you can use an
176             arrayref: it will be coerced to hashref, using the (coerced)
177             dependencies' names as keys.
178              
179             =head3 Examples
180              
181             service foo => (
182             class => 'Foo',
183             dependencies => {
184             { bar => { attribute => 12 } },
185             },
186             );
187              
188             The service C<foo> depends on the parameterized service C<bar>, and
189             C<bar> will be instantiated passing the hashref C<< { attribute => 12
190             } >> to its L<< C<get>|Bread::Board::Service::WithParameters/get >>
191             method.
192              
193             service foo => (
194             class => 'Foo',
195             dependencies => {
196             things => [ 'bar', 'baz' ],
197             },
198             );
199              
200             The service C<foo> depends on the services C<bar> and C<baz>, and when
201             instantiating C<foo>, its constructor will receive something like C<<
202             things => [ $instance_of_bar, $instance_of_baz ] >>.
203              
204             service foo => (
205             class => 'Foo',
206             dependencies => {
207             things => [
208             { bar => { attribute => 12 } },
209             { bar => { attribute => 27 } },
210             ],
211             },
212             );
213              
214             You can mix&match the coercions! This C<foo> will get two different
215             instances of C<bar> in its C<things> attribute, each C<bar>
216             instantiated with a different value.
217              
218             =head2 C<Bread::Board::Service::Parameters>
219              
220             Hashref mapping strings to L<MooseX::Params::Validate> specifications.
221              
222             Can be coerced from an arrayref of strings:
223              
224             [qw(a b c)]
225              
226             becomes:
227              
228             {
229             a => { optional => 0 },
230             b => { optional => 0 },
231             c => { optional => 0 },
232             }
233              
234             =head1 AUTHOR
235              
236             Stevan Little <stevan@iinteractive.com>
237              
238             =head1 BUGS
239              
240             Please report any bugs or feature requests on the bugtracker website
241             https://github.com/stevan/BreadBoard/issues
242              
243             When submitting a bug or request, please include a test-file or a
244             patch to an existing test-file that illustrates the bug or desired
245             feature.
246              
247             =head1 COPYRIGHT AND LICENSE
248              
249             This software is copyright (c) 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive.
250              
251             This is free software; you can redistribute it and/or modify it under
252             the same terms as the Perl 5 programming language system itself.
253              
254             =cut