File Coverage

blib/lib/MooseX/Attribute/ChainedClone.pm
Criterion Covered Total %
statement 27 35 77.1
branch 4 12 33.3
condition n/a
subroutine 9 11 81.8
pod n/a
total 40 58 68.9


line stmt bran cond sub pod time code
1             #
2             # This file is part of MooseX-Attribute-Chained
3             #
4             # This software is copyright (c) 2017 by Tom Hukins.
5             #
6             # This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #
9             package MooseX::Attribute::ChainedClone;
10             $MooseX::Attribute::ChainedClone::VERSION = '1.0.3';
11             # ABSTRACT: Attribute that returns a cloned instance
12 1     1   454500 use Moose::Util;
  1         3  
  1         9  
13             Moose::Util::meta_attribute_alias(
14             ChainedClone => 'MooseX::Traits::Attribute::ChainedClone' );
15              
16             package MooseX::Traits::Attribute::ChainedClone;
17             $MooseX::Traits::Attribute::ChainedClone::VERSION = '1.0.3';
18 1     1   557 use Moose::Role;
  1         4534  
  1         4  
19              
20             override accessor_metaclass => sub {
21             'MooseX::Attribute::ChainedClone::Method::Accessor';
22             };
23              
24             package MooseX::Attribute::ChainedClone::Method::Accessor;
25             $MooseX::Attribute::ChainedClone::Method::Accessor::VERSION = '1.0.3';
26 1     1   4729 use Carp qw(confess);
  1         3  
  1         47  
27 1     1   6 use Try::Tiny;
  1         2  
  1         46  
28 1     1   5 use base 'Moose::Meta::Method::Accessor';
  1         2  
  1         465  
29              
30             sub _generate_accessor_method_inline {
31 1     1   992 my $self = shift;
32 1         5 my $attr = $self->associated_attribute;
33 1 50       8 my $clone
34             = $attr->associated_class->has_method("clone")
35             ? '$_[0]->clone'
36             : 'bless { %{$_[0]} }, ref $_[0]';
37              
38 1 50       35 if ( $Moose::VERSION >= 1.9900 ) {
39             return try {
40 1     1   51 $self->_compile_code(
41             [ 'sub {',
42             'if (@_ > 1) {',
43             'my $clone = ' . $clone . ';',
44             $attr->_inline_set_value( '$clone', '$_[1]' ),
45             'return $clone;',
46             '}',
47             $attr->_inline_get_value('$_[0]'),
48             '}',
49             ]
50             );
51             }
52             catch {
53 0     0   0 confess "Could not generate inline accessor because : $_";
54 1         14 };
55             }
56             else {
57 0         0 my ( $code, $e ) = $self->_eval_closure(
58             {},
59             join( "\n",
60             'sub {',
61             'if (@_ > 1) {',
62             'my $clone = ' . $clone . ';',
63             $attr->inline_set( '$clone', '$_[1]' ),
64             'return $clone;',
65             '}',
66             $attr->inline_get('$_[0]'),
67             '}' ),
68             );
69 0 0       0 confess "Could not generate inline predicate because : $e" if $e;
70 0         0 return $code;
71             }
72             }
73              
74             sub _generate_writer_method_inline {
75 1     1   346 my $self = shift;
76 1         4 my $attr = $self->associated_attribute;
77 1 50       10 my $clone
78             = $attr->associated_class->has_method("clone")
79             ? '$_[0]->clone'
80             : 'bless { %{$_[0]} }, ref $_[0]';
81 1 50       31 if ( $Moose::VERSION >= 1.9900 ) {
82             return try {
83 1     1   41 $self->_compile_code(
84             [ 'sub {',
85             'my $clone = ' . $clone . ';',
86             $attr->_inline_set_value( '$clone', '$_[1]' ),
87             'return $clone;', '}',
88             ]
89             );
90             }
91             catch {
92 0     0     confess "Could not generate inline writer because : $_";
93 1         8 };
94             }
95             else {
96 0           my ( $code, $e ) = $self->_eval_closure(
97             {},
98             join( "\n",
99             'sub {',
100             'my $clone = ' . $clone . ';',
101             $attr->inline_set( '$clone', '$_[1]' ),
102             'return $clone;', '}' ),
103             );
104 0 0         confess "Could not generate inline writer because : $e" if $e;
105 0           return $code;
106             }
107             }
108              
109             1;
110              
111             __END__
112              
113             =pod
114              
115             =encoding UTF-8
116              
117             =head1 NAME
118              
119             MooseX::Attribute::ChainedClone - Attribute that returns a cloned instance
120              
121             =head1 VERSION
122              
123             version 1.0.3
124              
125             =head1 SYNOPSIS
126              
127             package Test;
128             use Moose;
129              
130             has debug => (
131             traits => [ 'ChainedClone' ],
132             is => 'rw',
133             isa => 'Bool',
134             default => 0,
135             );
136              
137             sub complex_method
138             {
139             my $self = shift;
140            
141             #...
142            
143             print "helper message" if $self->debug;
144            
145             #...
146             }
147            
148             sub clone {
149             my $self = shift;
150             # custom clone code here
151             # defaults to:
152             return bless { %$self }, ref $self;
153             }
154              
155              
156             1;
157              
158             Which allows for:
159              
160             my $test = Test->new;
161             $test->debug(1)->complex_method; # debug enabled
162             # complex_method is called on a cloned instance
163             # with debug set to 1
164              
165             $test->complex_method; # debug is still disabled on $test
166              
167             $test->debug(1); # returns a cloned $test instance with debug set to 1
168             $test->debug; # returns 0
169              
170             =head1 DESCRIPTION
171              
172             MooseX::Attribute::ChainedClone is a Moose Trait which allows for method chaining
173             on accessors by returning a cloned instance of C<$self> on write/set operations.
174              
175             If C<$self> has a C<clone> method, this method is invoked to clone the instance.
176             This allows for easy integration with L<MooseX::Clone> or any custom made
177             clone method. If no C<clone> method is available, the new instance is build
178             using C<< bless { %$self }, ref $self >>.
179              
180             =head1 AUTHORS
181              
182             =over 4
183              
184             =item *
185              
186             Tom Hukins <tom@eborcom.com>
187              
188             =item *
189              
190             Moritz Onken <onken@netcubed.de>
191              
192             =item *
193              
194             David McLaughlin <david@dmclaughlin.com>
195              
196             =back
197              
198             =head1 COPYRIGHT AND LICENSE
199              
200             This software is copyright (c) 2017 by Tom Hukins.
201              
202             This is free software; you can redistribute it and/or modify it under
203             the same terms as the Perl 5 programming language system itself.
204              
205             =head1 BUGS
206              
207             Please report any bugs or feature requests on the bugtracker website
208             L<http://rt.cpan.org/Public/Dist/Display.html?Name=MooseX-Attribute-Chained>
209             or by email to L<bug-moosex-attribute-chained at
210             rt.cpan.org|mailto:bug-moosex-attribute-chained at rt.cpan.org>.
211              
212             When submitting a bug or request, please include a test-file or a
213             patch to an existing test-file that illustrates the bug or desired
214             feature.
215              
216             =cut