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 |