File Coverage

lib/Badger/Mixin.pm
Criterion Covered Total %
statement 17 17 100.0
branch 3 6 50.0
condition 1 3 33.3
subroutine 3 3 100.0
pod 2 2 100.0
total 26 31 83.8


line stmt bran cond sub pod time code
1             #========================================================================
2             #
3             # Badger::Mixin
4             #
5             # DESCRIPTION
6             # Base class for mixins that allow you to "mix in" functionality using
7             # composition rather than inheritance. Similar in concept to roles,
8             # although operating at a slightly lower level.
9             #
10             # AUTHOR
11             # Andy Wardley
12             #
13             #========================================================================
14              
15             package Badger::Mixin;
16              
17             use Badger::Class
18 1         6 version => 3.00,
19             debug => 0,
20             base => 'Badger::Exporter',
21             import => 'class',
22             constants => 'PKG REFS ONCE ARRAY DELIMITER',
23 1     1   2137 words => 'EXPORT_TAGS MIXINS';
  1         2  
24              
25              
26             sub mixin {
27 3     3 1 4 my $self = shift;
28 3   33     7 my $target = shift || (caller())[0];
29 3         6 my $class = $self->class;
30 3         7 my $mixins = $class->list_vars(MIXINS);
31 3 50       5 $self->debug("mixinto($target): ", $self->dump_data($mixins), "\n") if $DEBUG;
32 3         7 $self->export($target, $mixins);
33             }
34              
35             sub mixins {
36 3     3 1 4 my $self = shift;
37 3 50       7 my $syms = @_ == 1 ? shift : [ @_ ];
38 3         8 my $class = $self->class;
39 3         8 my $mixins = $class->var_default(MIXINS, [ ]);
40            
41 3 50       23 $syms = [ split(DELIMITER, $syms) ]
42             unless ref $syms eq ARRAY;
43              
44 3         33 push(@$mixins, @$syms);
45 3         16 $self->export_any($syms);
46            
47 3         4 return $mixins;
48             }
49              
50              
51             1;
52              
53             =head1 NAME
54              
55             Badger::Mixin - base class mixin object
56              
57             =head1 SYNOPSIS
58              
59             The C module is a base class for mixin modules.
60             You can use the L module to declare mixins:
61              
62             package Your::Mixin::Module;
63            
64             use Badger::Class
65             mixins => '$FOO @BAR %BAZ bam';
66            
67             # some sample data/methods to mixin
68             our $FOO = 'Some random text';
69             our @BAR = qw( foo bar baz );
70             our %BAZ = ( hello => 'world' );
71             sub bam { 'just testing' };
72              
73             Behind the scenes this adds C as a base class of
74             C and calls the L method to declare
75             what symbols can be mixed into another module. You can write this
76             code manually if you prefer:
77              
78             package Your::Mixin::Module;
79            
80             use base 'Badger::Mixin';
81            
82             __PACKAGE__->mixins('$FOO @BAR %BAZ bam');
83            
84             # sample data/methods as before
85              
86             =head1 DESCRIPTION
87              
88             The L module is a base class for mixin modules. Mixins are
89             modules that implement functionality that can be mixed into other modules.
90             This allows you to create modules using composition instead of misuing
91             inheritance.
92              
93             The easiest way to define a mixin module is via the C module.
94              
95             package Your::Mixin::Module;
96            
97             use Badger::Class
98             mixins => '$FOO @BAR %BAZ bam';
99              
100             This is syntactic sugar for the following code:
101              
102             package Your::Mixin::Module;
103            
104             use base 'Badger::Mixin';
105             __PACKAGE__->mixins('$FOO @BAR %BAZ bam');
106              
107             The mixin module declares what symbols it makes available for mixing using the
108             L (plural) method (either indirectly as in the first example,
109             or directly as in the second).
110              
111             The L (singular) method can then be used to mix those symbols into
112             another module. L provides the L
113             hook which you can use:
114              
115             package Your::Other::Module;
116            
117             use Badger::Class
118             mixin => 'Your::Mixin::Module';
119              
120             Or you can call the L method manually if you prefer.
121              
122             package Your::Other::Module;
123            
124             use Your::Mixin::Module;
125             Your::Mixin::Module->mixin(__PACKAGE__);
126              
127             Mixins are little more than modules with a specialised export mechanism. In
128             fact, the C module uses the L behind the
129             scenes to export the mixin symbols into the target package. Mixins are
130             intentionally simple. If you want to do anything more complicated in terms of
131             exporting symbols then you should use the L module directly
132             instead.
133              
134             =head1 METHODS
135              
136             =head2 mixins($symbols)
137              
138             This method is used to declare what symbols are available for mixing in to
139             other packages. Symbols can be specified as a list of items, a reference to a
140             list of items or as a single whitespace delimited string.
141              
142             package Your::Module;
143             use base 'Badger::Mixin';
144            
145             # either list of symbols...
146             __PACKAGE__->mixins('$FOO', '@BAR', '%BAZ', 'bam');
147            
148             # ...or reference to a list
149             __PACKAGE__->mixins(['$FOO', '@BAR', '%BAZ', 'bam']);
150            
151             # ...or single string of whitespace delimited symbols
152             __PACKAGE__->mixins('$FOO @BAR %BAZ bam');
153              
154             =head2 mixin($package)
155              
156             This method is used to mixin the symbols declared via L into
157             the package specified by the C<$package> argument.
158              
159             Your::Mixin::Module->mixin('My::Module');
160              
161             =head1 AUTHOR
162              
163             Andy Wardley L
164              
165             =head1 COPYRIGHT
166              
167             Copyright (C) 2005-2009 Andy Wardley. All rights reserved.
168              
169             =head1 SEE ALSO
170              
171             L
172              
173             =cut
174              
175             # Local Variables:
176             # mode: Perl
177             # perl-indent-level: 4
178             # indent-tabs-mode: nil
179             # End:
180             #
181             # vim: expandtab shiftwidth=4:
182             # TextMate: rocks my world