File Coverage

blib/lib/Kelp/Base.pm
Criterion Covered Total %
statement 54 55 98.1
branch 13 14 92.8
condition 7 9 77.7
subroutine 14 14 100.0
pod 0 2 0.0
total 88 94 93.6


line stmt bran cond sub pod time code
1             package Kelp::Base;
2              
3 43     43   37806 use strict ();
  43         268  
  43         1036  
4 43     43   209 use warnings ();
  43         74  
  43         556  
5 43     43   191 use feature ();
  43         112  
  43         682  
6 43     43   209 use Carp;
  43         98  
  43         3974  
7 43     43   22060 use namespace::autoclean ();
  43         866117  
  43         2699  
8              
9             sub import {
10 572     572   57344 my $class = shift;
11 572         1360 my $caller = caller;
12              
13             # Do not import into inherited classes
14 572 100       31319 return if $class ne __PACKAGE__;
15              
16 442   66     1682 my $base = shift || $class;
17              
18 442 100       1099 if ( $base ne '-strict' ) {
19 43     43   340 no strict 'refs';
  43         90  
  43         1253  
20 43     43   224 no warnings 'redefine';
  43         85  
  43         13545  
21              
22 376         709 my $file = $base;
23 376         3463 $file =~ s/::|'/\//g;
24 376 100       46797 require "$file.pm" unless $base->can('new'); # thanks sri
25              
26 376         1048066 push @{"${caller}::ISA"}, $base;
  376         4424  
27 376     1552   1709 *{"${caller}::attr"} = sub { attr( $caller, @_ ) };
  376         1759  
  1552         4084  
28             }
29              
30 442         2830 strict->import;
31 442         4175 warnings->import;
32 442         30415 feature->import(':5.10');
33              
34 442         3334 namespace::autoclean->import(
35             -cleanee => scalar(caller),
36             );
37             }
38              
39             sub new {
40 545     545 0 6801 bless { @_[ 1 .. $#_ ] }, $_[0];
41             }
42              
43             sub attr {
44 1554     1554 0 3102 my ( $class, $name, $default ) = @_;
45              
46 1554 50 66     5430 if ( ref $default && ref $default ne 'CODE' ) {
47 0         0 croak "Default value for '$name' can not be a reference.";
48             }
49              
50 43     43   364 no strict 'refs';
  43         95  
  43         1640  
51 43     43   275 no warnings 'redefine';
  43         2154  
  43         8926  
52              
53             # Readonly attributes are marked with '-'
54 1554         3655 my $readonly = $name =~ s/^\-//;
55              
56 1554         7175 *{"${class}::$name"} = sub {
57 16947 100 100 16947   51138 if ( @_ > 1 && !$readonly ) {
58 1937         7286 $_[0]->{$name} = $_[1];
59             }
60 16947 100       67687 return $_[0]->{$name} if exists $_[0]->{$name};
61 1987 100       7960 return $_[0]->{$name} =
62             ref $default eq 'CODE'
63             ? $default->( $_[0] )
64             : $default;
65 1554         4835 };
66             }
67              
68             1;
69              
70             __END__
71              
72             =pod
73              
74             =head1 NAME
75              
76             Kelp::Base - Simple lazy attributes
77              
78             =head1 SYNOPSIS
79              
80             use Kelp::Base;
81              
82             attr source => 'dbi:mysql:users';
83             attr user => 'test';
84             attr pass => 'secret';
85             attr opts => sub { { PrintError => 1, RaiseError => 1 } };
86              
87             attr dbh => sub {
88             my $self = shift;
89             DBI->connect( $self->sourse, $self->user, $self->pass, $self->opts );
90             };
91              
92             # Later ...
93             sub do_stuff {
94             my $self = shift;
95             $self->dbh->do('DELETE FROM accounts');
96             }
97              
98             or
99              
100             use Kelp::Base 'Module::Name'; # Extend Module::Name
101              
102             or
103              
104             use Kelp::Base -strict; # Only use strict, warnings and v5.10
105             # No magic
106              
107              
108             =head1 DESCRIPTION
109              
110             This module provides simple lazy attributes.
111              
112             =head1 WHY?
113              
114             Some users will naturally want to ask F<"Why not use Moose/Mouse/Moo/Mo?">. The
115             answer is that the Kelp web framework needs lazy attributes, but the
116             author wanted to keep the code light and object manager agnostic.
117             This allows the users of the framework to choose an object manager to
118             their liking.
119             There is nothing more annoying than a module that forces you to use L<Moose> when you
120             are perfectly fine with L<Moo> or L<Mo>, for example.
121              
122             =head1 USAGE
123              
124             use Kelp::Base;
125              
126             The above will automatically include C<strict>, C<warnings> and C<v5.10>. It will
127             also inject a new sub in the current class called C<attr>.
128              
129             attr name1 => 1; # Fixed value
130             attr name2 => sub { [ 1, 2, 3 ] }; # Array
131             attr name3 => sub {
132             $_[0]->other;
133             }
134              
135             ...
136              
137             say $self->name1; # 1
138             $self->name2( [ 6, 7, 8 ] ); # Set new value
139              
140             All those attributes will be available for reading and writing in each instance
141             of the current class. If you want to create a read-only attribute, prefix its
142             name with a dash.
143              
144             attr -readonly => "something";
145              
146             # Later
147             say $self->readonly; # something
148             $self->readonly("nothing"); # no change
149              
150             =head1 SEE ALSO
151              
152             L<Kelp>, L<Moose>, L<Moo>, L<Mo>, L<Any::Moose>
153              
154             =cut