File Coverage

blib/lib/MooseX/Clone.pm
Criterion Covered Total %
statement 38 38 100.0
branch 7 8 87.5
condition n/a
subroutine 9 9 100.0
pod 1 2 50.0
total 55 57 96.4


line stmt bran cond sub pod time code
1             package MooseX::Clone; # git description: 0.05-13-gd83ae68
2             # ABSTRACT: Fine-grained cloning support for Moose objects.
3              
4             our $VERSION = '0.06';
5              
6 2     2   2764 use Moose::Role;
  2         8640  
  2         9  
7 2     2   12484 use Hash::Util::FieldHash::Compat qw(idhash);
  2         4648  
  2         8  
8 2     2   1487 use MooseX::Clone::Meta::Attribute::Trait::Clone;
  2         8  
  2         73  
9 2     2   1458 use MooseX::Clone::Meta::Attribute::Trait::StorableClone;
  2         68  
  2         106  
10 2     2   1892 use MooseX::Clone::Meta::Attribute::Trait::NoClone;
  2         8  
  2         81  
11 2     2   1827 use MooseX::Clone::Meta::Attribute::Trait::Copy;
  2         8  
  2         88  
12 2     2   13 use namespace::autoclean;
  2         3  
  2         12  
13              
14             sub clone {
15 8     8 1 41478 my ( $self, %params ) = @_;
16              
17 8         42 my $meta = $self->meta;
18              
19 8         124 my @cloning;
20              
21 8         39 idhash my %clone_args;
22              
23 8         174 attr: foreach my $attr ($meta->get_all_attributes()) {
24             # collect all attrs that can be cloned.
25             # if they have args in %params then those are passed to the recursive cloning op
26 28 100       1119 if ( $attr->does("MooseX::Clone::Meta::Attribute::Trait::Clone::Base") ) {
27 23         6529 push @cloning, $attr;
28              
29 23 50       91 if ( defined( my $init_arg = $attr->init_arg ) ) {
30 23 100       115 if ( exists $params{$init_arg} ) {
31 2         20 $clone_args{$attr} = delete $params{$init_arg};
32             }
33             }
34             }
35             }
36              
37 8         240 my $clone = $meta->clone_object($self, %params);
38              
39 8         1615 foreach my $attr ( @cloning ) {
40             $clone->clone_attribute(
41             proto => $self,
42             attr => $attr,
43 23 100       2869 ( exists $clone_args{$attr} ? ( init_arg => $clone_args{$attr} ) : () ),
44             );
45             }
46              
47 8         2804 return $clone;
48             }
49              
50             sub clone_attribute {
51 23     23 0 62 my ( $self, %args ) = @_;
52              
53 23         39 my ( $proto, $attr ) = @args{qw/proto attr/};
54              
55 23         120 $attr->clone_value( $self, $proto, %args );
56             }
57              
58             __PACKAGE__
59              
60             __END__
61              
62             =pod
63              
64             =encoding UTF-8
65              
66             =head1 NAME
67              
68             MooseX::Clone - Fine-grained cloning support for Moose objects.
69              
70             =head1 VERSION
71              
72             version 0.06
73              
74             =head1 SYNOPSIS
75              
76             package Bar;
77             use Moose;
78              
79             with qw(MooseX::Clone);
80              
81             has foo => (
82             isa => "Foo",
83             traits => [qw(Clone)], # this attribute will be recursively cloned
84             );
85              
86             package Foo;
87             use Moose;
88              
89             # this API is used/provided by MooseX::Clone
90             sub clone {
91             my ( $self, %params ) = @_;
92              
93             # ...
94             }
95              
96              
97             # used like this:
98              
99             my $bar = Bar->new( foo => Foo->new );
100              
101             my $copy = $bar->clone( foo => [ qw(Args for Foo::clone) ] );
102              
103             =head1 DESCRIPTION
104              
105             Out of the box L<Moose> only provides very barebones cloning support in order
106             to maximize flexibility.
107              
108             This role provides a C<clone> method that makes use of the low level cloning
109             support already in L<Moose> and adds selective deep cloning based on
110             introspection on top of that. Attributes with the C<Clone> trait will handle
111             cloning of data within the object, typically delegating to the attribute
112             value's own C<clone> method.
113              
114             =head1 TRAITS
115              
116             =over 4
117              
118             =item Clone
119              
120             By default Moose objects are cloned like this:
121              
122             bless { %$old }, ref $old;
123              
124             By specifying the L<Clone> trait for certain attributes custom behavior the
125             value's own C<clone> method will be invoked.
126              
127             By extending this trait you can create custom cloning for certain attributes.
128              
129             By creating C<clone> methods for your objects (e.g. by composing
130             L<MooseX::Compile>) you can make them interact with this trait.
131              
132             =item NoClone
133              
134             Specifies attributes that should be skipped entirely while cloning.
135              
136             =back
137              
138             =head1 METHODS
139              
140             =over 4
141              
142             =item clone %params
143              
144             Returns a clone of the object.
145              
146             All attributes which do the L<MooseX::Clone::Meta::Attribute::Trait::Clone>
147             role will handle cloning of that attribute. All other fields are plainly copied
148             over, just like in L<Class::MOP::Class/clone_object>.
149              
150             Attributes whose C<init_arg> is in %params and who do the C<Clone> trait will
151             get that argument passed to the C<clone> method (dereferenced). If the
152             attribute does not self-clone then the param is used normally by
153             L<Class::MOP::Class/clone_object>, that is it will simply shadow the previous
154             value, and does not have to be an array or hash reference.
155              
156             =back
157              
158             =head1 TODO
159              
160             Refactor to work in term of a metaclass trait so that C<< meta->clone_object >>
161             will still do the right thing.
162              
163             =head1 THANKS
164              
165             clkao made the food required to write this module
166              
167             =head1 AUTHOR
168              
169             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
170              
171             =head1 COPYRIGHT AND LICENSE
172              
173             This software is copyright (c) 2008 by יובל קוג'מן (Yuval Kogman).
174              
175             This is free software; you can redistribute it and/or modify it under
176             the same terms as the Perl 5 programming language system itself.
177              
178             =cut