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   36126 use strict ();
  43         257  
  43         1039  
4 43     43   242 use warnings ();
  43         78  
  43         553  
5 43     43   189 use feature ();
  43         77  
  43         732  
6 43     43   209 use Carp;
  43         121  
  43         3747  
7 43     43   21840 use namespace::autoclean ();
  43         839536  
  43         2557  
8              
9             sub import {
10 572     572   56222 my $class = shift;
11 572         1335 my $caller = caller;
12              
13             # Do not import into inherited classes
14 572 100       31222 return if $class ne __PACKAGE__;
15              
16 442   66     1661 my $base = shift || $class;
17              
18 442 100       1077 if ( $base ne '-strict' ) {
19 43     43   332 no strict 'refs';
  43         99  
  43         1235  
20 43     43   228 no warnings 'redefine';
  43         111  
  43         13153  
21              
22 376         622 my $file = $base;
23 376         3357 $file =~ s/::|'/\//g;
24 376 100       46008 require "$file.pm" unless $base->can('new'); # thanks sri
25              
26 376         1020826 push @{"${caller}::ISA"}, $base;
  376         4238  
27 376     1552   1709 *{"${caller}::attr"} = sub { attr( $caller, @_ ) };
  376         1757  
  1552         3980  
28             }
29              
30 442         2827 strict->import;
31 442         4078 warnings->import;
32 442         29561 feature->import(':5.10');
33              
34 442         3131 namespace::autoclean->import(
35             -cleanee => scalar(caller),
36             );
37             }
38              
39             sub new {
40 545     545 0 6343 bless { @_[ 1 .. $#_ ] }, $_[0];
41             }
42              
43             sub attr {
44 1554     1554 0 3132 my ( $class, $name, $default ) = @_;
45              
46 1554 50 66     5284 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   349 no strict 'refs';
  43         106  
  43         1540  
51 43     43   274 no warnings 'redefine';
  43         80  
  43         10846  
52              
53             # Readonly attributes are marked with '-'
54 1554         3654 my $readonly = $name =~ s/^\-//;
55              
56 1554         7020 *{"${class}::$name"} = sub {
57 16947 100 100 16947   49008 if ( @_ > 1 && !$readonly ) {
58 1937         7087 $_[0]->{$name} = $_[1];
59             }
60 16947 100       65427 return $_[0]->{$name} if exists $_[0]->{$name};
61 1987 100       7808 return $_[0]->{$name} =
62             ref $default eq 'CODE'
63             ? $default->( $_[0] )
64             : $default;
65 1554         4716 };
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