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              
2             use strict ();
3 43     43   31718 use warnings ();
  43         231  
  43         852  
4 43     43   163 use feature ();
  43         68  
  43         459  
5 43     43   157 use Carp;
  43         60  
  43         587  
6 43     43   160 use namespace::autoclean ();
  43         83  
  43         3237  
7 43     43   16858  
  43         718058  
  43         2093  
8             my $class = shift;
9             my $caller = caller;
10 572     572   49505  
11 572         1137 # Do not import into inherited classes
12             return if $class ne __PACKAGE__;
13              
14 572 100       27462 my $base = shift || $class;
15              
16 442   66     1334 if ( $base ne '-strict' ) {
17             no strict 'refs';
18 442 100       908 no warnings 'redefine';
19 43     43   278  
  43         74  
  43         2512  
20 43     43   184 my $file = $base;
  43         68  
  43         11222  
21             $file =~ s/::|'/\//g;
22 376         545 require "$file.pm" unless $base->can('new'); # thanks sri
23 376         2756  
24 376 100       36306 push @{"${caller}::ISA"}, $base;
25             *{"${caller}::attr"} = sub { attr( $caller, @_ ) };
26 376         841994 }
  376         3690  
27 376     1552   1392  
  376         1499  
  1552         3411  
28             strict->import;
29             warnings->import;
30 442         2408 feature->import(':5.10');
31 442         3626  
32 442         24285 namespace::autoclean->import(
33             -cleanee => scalar(caller),
34 442         2624 );
35             }
36              
37             bless { @_[ 1 .. $#_ ] }, $_[0];
38             }
39              
40 545     545 0 5341 my ( $class, $name, $default ) = @_;
41              
42             if ( ref $default && ref $default ne 'CODE' ) {
43             croak "Default value for '$name' can not be a reference.";
44 1554     1554 0 2575 }
45              
46 1554 50 66     4670 no strict 'refs';
47 0         0 no warnings 'redefine';
48              
49             # Readonly attributes are marked with '-'
50 43     43   285 my $readonly = $name =~ s/^\-//;
  43         87  
  43         1310  
51 43     43   222  
  43         89  
  43         7414  
52             *{"${class}::$name"} = sub {
53             if ( @_ > 1 && !$readonly ) {
54 1554         2953 $_[0]->{$name} = $_[1];
55             }
56 1554         5958 return $_[0]->{$name} if exists $_[0]->{$name};
57 16947 100 100 16947   41425 return $_[0]->{$name} =
58 1937         5959 ref $default eq 'CODE'
59             ? $default->( $_[0] )
60 16947 100       53853 : $default;
61 1987 100       6417 };
62             }
63              
64             1;
65 1554         4091  
66              
67             =pod
68              
69             =head1 NAME
70              
71             Kelp::Base - Simple lazy attributes
72              
73             =head1 SYNOPSIS
74              
75             use Kelp::Base;
76              
77             attr source => 'dbi:mysql:users';
78             attr user => 'test';
79             attr pass => 'secret';
80             attr opts => sub { { PrintError => 1, RaiseError => 1 } };
81              
82             attr dbh => sub {
83             my $self = shift;
84             DBI->connect( $self->sourse, $self->user, $self->pass, $self->opts );
85             };
86              
87             # Later ...
88             sub do_stuff {
89             my $self = shift;
90             $self->dbh->do('DELETE FROM accounts');
91             }
92              
93             or
94              
95             use Kelp::Base 'Module::Name'; # Extend Module::Name
96              
97             or
98              
99             use Kelp::Base -strict; # Only use strict, warnings and v5.10
100             # No magic
101              
102              
103             =head1 DESCRIPTION
104              
105             This module provides simple lazy attributes.
106              
107             =head1 WHY?
108              
109             Some users will naturally want to ask F<"Why not use Moose/Mouse/Moo/Mo?">. The
110             answer is that the Kelp web framework needs lazy attributes, but the
111             author wanted to keep the code light and object manager agnostic.
112             This allows the users of the framework to choose an object manager to
113             their liking.
114             There is nothing more annoying than a module that forces you to use L<Moose> when you
115             are perfectly fine with L<Moo> or L<Mo>, for example.
116              
117             =head1 USAGE
118              
119             use Kelp::Base;
120              
121             The above will automatically include C<strict>, C<warnings> and C<v5.10>. It will
122             also inject a new sub in the current class called C<attr>.
123              
124             attr name1 => 1; # Fixed value
125             attr name2 => sub { [ 1, 2, 3 ] }; # Array
126             attr name3 => sub {
127             $_[0]->other;
128             }
129              
130             ...
131              
132             say $self->name1; # 1
133             $self->name2( [ 6, 7, 8 ] ); # Set new value
134              
135             All those attributes will be available for reading and writing in each instance
136             of the current class. If you want to create a read-only attribute, prefix its
137             name with a dash.
138              
139             attr -readonly => "something";
140              
141             # Later
142             say $self->readonly; # something
143             $self->readonly("nothing"); # no change
144              
145             =head1 SEE ALSO
146              
147             L<Kelp>, L<Moose>, L<Moo>, L<Mo>, L<Any::Moose>
148              
149             =cut