File Coverage

blib/lib/Class/MakeMethods/Composite/Universal.pm
Criterion Covered Total %
statement 17 17 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod 2 2 100.0
total 26 26 100.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Class::MakeMethods::Composite::Universal - Composite Method Tricks
4              
5             =head1 SYNOPSIS
6              
7             Class::MakeMethods::Composite::Universal->make_patch(
8             -TargetClass => 'SomeClass::OverYonder',
9             name => 'foo',
10             pre_rules => [
11             sub {
12             my $method = pop;
13             warn "Arguments for foo:", @_
14             }
15             ]
16             post_rules => [
17             sub {
18             warn "Result of foo:", Class::MakeMethods::Composite->CurrentResults
19             }
20             ]
21             );
22              
23             =head1 DESCRIPTION
24              
25             The Composite::Universal suclass of MakeMethods provides some generally-applicable types of methods based on Class::MakeMethods::Composite.
26              
27             =cut
28              
29             package Class::MakeMethods::Composite::Universal;
30              
31             $VERSION = 1.000;
32 1     1   8698 use strict;
  1         3  
  1         45  
33 1     1   639 use Class::MakeMethods::Composite '-isasubclass';
  1         2  
  1         10  
34 1     1   6 use Carp;
  1         2  
  1         77  
35              
36             ########################################################################
37              
38             =head1 METHOD GENERATOR TYPES
39              
40             =head2 patch
41              
42             The patch ruleset generates composites whose core behavior is based on an existing subroutine.
43              
44             Here's a sample usage:
45              
46             sub foo {
47             my $count = shift;
48             return 'foo' x $count;
49             }
50            
51             Class::MakeMethods::Composite::Universal->make(
52             -ForceInstall => 1,
53             patch => {
54             name => 'foo',
55             pre_rules => [
56             sub {
57             my $method = pop @_;
58             if ( ! scalar @_ ) {
59             @{ $method->{args} } = ( 2 );
60             }
61             },
62             sub {
63             my $method = pop @_;
64             my $count = shift;
65             if ( $count > 99 ) {
66             Carp::confess "Won't foo '$count' -- that's too many!"
67             }
68             },
69             ],
70             post_rules => [
71             sub {
72             my $method = pop @_;
73             if ( ref $method->{result} eq 'SCALAR' ) {
74             ${ $method->{result} } =~ s/oof/oozle-f/g;
75             } elsif ( ref $method->{result} eq 'ARRAY' ) {
76             map { s/oof/oozle-f/g } @{ $method->{result} };
77             }
78             }
79             ],
80             },
81             );
82              
83             =cut
84              
85 1     1   6 use vars qw( %PatchFragments );
  1         2  
  1         114  
86              
87             sub patch {
88 1     1 1 10 (shift)->_build_composite( \%PatchFragments, @_ );
89             }
90              
91             %PatchFragments = (
92             '' => [
93             '+init' => sub {
94             my $method = pop @_;
95             my $origin = ( $Class::MethodMaker::CONTEXT{TargetClass} || '' ) .
96             '::' . $method->{name};
97 1     1   5 no strict 'refs';
  1         1  
  1         185  
98             $method->{patch_original} = *{ $origin }{CODE}
99             or croak "No subroutine $origin() to patch";
100             },
101             'do' => sub {
102             my $method = pop @_;
103             my $sub = $method->{patch_original};
104             &$sub( @_ );
105             },
106             ],
107             );
108              
109             =head2 make_patch
110              
111             A convenient wrapper for C and the C method generator.
112              
113             Provides the '-ForceInstall' flag, which is required to ensure that the patched subroutine replaces the original.
114              
115             For example, one could add logging to an existing method as follows:
116              
117             Class::MakeMethods::Composite::Universal->make_patch(
118             -TargetClass => 'SomeClass::OverYonder',
119             name => 'foo',
120             pre_rules => [
121             sub {
122             my $method = pop;
123             warn "Arguments for foo:", @_
124             }
125             ]
126             post_rules => [
127             sub {
128             warn "Result of foo:", Class::MakeMethods::Composite->CurrentResults
129             }
130             ]
131             );
132              
133             =cut
134              
135             sub make_patch {
136 1     1 1 2186 (shift)->make( -ForceInstall => 1, patch => { @_ } );
137             }
138              
139              
140             ########################################################################
141              
142             =head1 SEE ALSO
143              
144             See L for general information about this distribution.
145              
146             See L for more about this family of subclasses.
147              
148             =cut
149              
150             1;