File Coverage

blib/lib/Bolts/Meta/Attribute/Trait/Initializer.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             package Bolts::Meta::Attribute::Traits::Initializer;
2             $Bolts::Meta::Attribute::Traits::Initializer::VERSION = '0.142930';
3             # ABSTRACT: Build an attribute with an initializer
4              
5 8     8   2641 use Moose::Role;
  8         21144  
  8         39  
6 8     8   38554 use Safe::Isa;
  8         2079  
  8         1088  
7              
8             Moose::Util::meta_attribute_alias('Bolts::Initializer');
9              
10              
11             # TODO Make this into a helper class so that other kinds of init can be added
12             # and customized later.
13 8     8   77 use Moose::Util::TypeConstraints;
  8         12  
  8         51  
14             has init_type => (
15             is => 'ro',
16             isa => enum([qw( Array Scalar )]),
17             required => 1,
18             default => 'Scalar',
19             );
20 8     8   12231 no Moose::Util::TypeConstraints;
  8         14  
  8         38  
21              
22              
23             has special_initializer => (
24             is => 'ro',
25             isa => 'Str',
26             required => 1,
27             );
28              
29             has _original_default => (
30             is => 'rw',
31             predicate => '_has_original_default',
32             );
33              
34             before install_accessors => sub {
35             my $self = shift;
36             my $meta = $self->associated_class;
37              
38             $meta->add_attribute($self->special_initializer => (
39             is => 'ro',
40             required => $self->is_required,
41             init_arg => $self->name,
42             ($self->_has_original_default ? (
43             default => $self->_original_default
44             ) : ()),
45             ));
46             };
47              
48             before _process_options => sub {
49             my ($self, $name, $options) = @_;
50              
51             # Having these here is probably a sign that we're doing this wrong.
52             # Should probably just have the default call some predefined subroutine
53             # instead and skip these bits here.
54             $options->{special_initializer} //= '_' . $name . '_initializer';
55             $options->{init_type} //= 'Scalar';
56              
57             my $_initializer = $options->{special_initializer};
58              
59             $options->{_original_default} = delete $options->{default}
60             if exists $options->{default};
61              
62             $options->{init_arg} = undef;
63             $options->{lazy} = 1;
64              
65             if ($options->{init_type} eq 'Scalar') {
66             $options->{default} = sub {
67             my $self = shift;
68              
69             my $init = $self->$_initializer;
70             if ($init->$_isa('Bolts::Meta::Initializer')) {
71             return $self->initialize_value($init->get);
72             }
73             else {
74             return $init;
75             }
76             };
77             }
78             else {
79             $options->{default} = sub {
80             my $self = shift;
81              
82             my @values;
83             my $init_array = $self->$_initializer;
84             for my $init (@$init_array) {
85             if ($init->$_isa('Bolts::Meta::Initializer')) {
86             push @values, $self->initialize_value($init->get);
87             }
88             else {
89             push @values, $init;
90             }
91             }
92              
93             return \@values;
94             };
95             }
96             };
97              
98             1;
99              
100             __END__
101              
102             =pod
103              
104             =encoding UTF-8
105              
106             =head1 NAME
107              
108             Bolts::Meta::Attribute::Traits::Initializer - Build an attribute with an initializer
109              
110             =head1 VERSION
111              
112             version 0.142930
113              
114             =head1 DESCRIPTION
115              
116             Sometimes it can be handy to partially break inversion of control to allow an object some control over it's own destiny. This attribute, given the short alias L<Bolts::Initializer>, can help you do that.
117              
118             See L<Bolts::Role::Initializer> for details and a synopsis.
119              
120             =head1 ATTRIBUTES
121              
122             =head2 init_type
123              
124             This is the type of initialization to perform on the intializer. It may be set to either "Array" or "Scalar" and defaults to "Scalar".
125              
126             =over
127              
128             =item Scalar
129              
130             The initializer is given as a single value. Either the actual value to be passed through or a L<Bolts::Meta::Initializer> object.
131              
132             =item Array
133              
134             The initializer is given as an array reference of values. Each element of the array may be a L<Bolts::Meta::Initializer> object or a real object to place in the array as is.
135              
136             =back
137              
138             =head2 special_initializer
139              
140             This is the name of the secondary attribute to use as the hidden initializer attribute. It defaults to C<<"_${name}_initializer">>, where C<<${name}>> is the name of this attribute.
141              
142             =head1 AUTHOR
143              
144             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
145              
146             =head1 COPYRIGHT AND LICENSE
147              
148             This software is copyright (c) 2014 by Qubling Software LLC.
149              
150             This is free software; you can redistribute it and/or modify it under
151             the same terms as the Perl 5 programming language system itself.
152              
153             =cut