File Coverage

blib/lib/Method/Generate/Accessor/Role/LvalueAttribute.pm
Criterion Covered Total %
statement 27 27 100.0
branch 4 4 100.0
condition n/a
subroutine 8 8 100.0
pod n/a
total 39 39 100.0


line stmt bran cond sub pod time code
1             #
2             # This file is part of MooX-LvalueAttribute
3             #
4             # This software is copyright (c) 2013 by Damien "dams" Krotkine.
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 Method::Generate::Accessor::Role::LvalueAttribute;
10             {
11             $Method::Generate::Accessor::Role::LvalueAttribute::VERSION = '0.16';
12             }
13 3     3   536428 use strictures 1;
  3         28  
  3         94  
14              
15             # ABSTRACT: Provides Lvalue accessors to Moo class attributes
16              
17 3     3   247 use Moo::Role;
  3         8  
  3         24  
18 3     3   5948 use Variable::Magic qw(wizard cast);
  3         6189  
  3         372  
19              
20 3     3   2381 use Hash::Util::FieldHash::Compat;
  3         287984  
  3         29  
21              
22             Hash::Util::FieldHash::Compat::fieldhash my %LVALUES;
23              
24             require MooX::LvalueAttribute;
25              
26             around generate_method => sub {
27             my $orig = shift;
28             my $self = shift;
29             # would like a better way to disable XS
30              
31             my ($into, $name, $spec, $quote_opts) = @_;
32              
33             $MooX::LvalueAttribute::INJECTED_IN_ROLE{$into}
34             || $MooX::LvalueAttribute::INJECTED_IN_CLASS{$into}
35             or return $self->$orig(@_);
36              
37             if ($spec->{lvalue}) {
38              
39             my $is = $spec->{is};
40             if ($is eq 'rw') {
41             $spec->{accessor} = $name unless exists $spec->{accessor}
42             or ( $spec->{reader} and $spec->{writer} );
43             } elsif ($is eq 'rwp') {
44             $spec->{writer} = "_set_${name}" unless exists $spec->{writer};
45             }
46              
47             exists $spec->{writer} || exists $spec->{accessor}
48             or die "lvalue was set but no accessor nor reader, and attribute is not rw";
49             foreach( qw(writer accessor) ) {
50             my $t = $spec->{$_}
51             or next;
52             $spec->{'lv_' . $_} = $t;
53             $spec->{$_} = '_lv_' . $t;
54             }
55             }
56              
57             my $methods = $self->$orig(@_);
58              
59             foreach ( qw(writer accessor) ) {
60             my $lv_name = $spec->{'lv_' . $_}
61             or next;
62             my $name = $spec->{$_};
63 3     3   1406 no strict 'refs';
  3         8  
  3         1304  
64             my $sub = sub : lvalue {
65 27     27   21016 my $self = shift;
66 27 100       162 if (! exists $LVALUES{$self}{$lv_name}) {
67             my $wiz = wizard(
68             set => sub {
69 7     7   12 $self->$name(${$_[0]});
  7         29  
70 7         382 return 1;
71             },
72             get => sub {
73 17     17   331 ${$_[0]} = $self->$name();
  17         454  
74 17         61 return 1;
75             },
76 10         87 );
77 10         325 cast $LVALUES{$self}{$lv_name}, $wiz;
78             }
79 27 100       70 @_ and $self->$name(@_);
80 27         175 $LVALUES{$self}{$lv_name};
81             };
82             $methods->{$lv_name} = $sub;
83             *{"${into}::${lv_name}"} = $sub;
84             }
85             };
86              
87             1;
88              
89             __END__