line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mandel::Model; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Mandel::Model - An object modelling a document |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 DESCRIPTION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
This class is used to descrieb the structure of L |
10
|
|
|
|
|
|
|
in mongodb. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=cut |
13
|
|
|
|
|
|
|
|
14
|
27
|
|
|
27
|
|
171
|
use Mojo::Base -base; |
|
27
|
|
|
|
|
64
|
|
|
27
|
|
|
|
|
351
|
|
15
|
27
|
|
|
27
|
|
10309
|
use Mojo::Loader 'load_class'; |
|
27
|
|
|
|
|
42577
|
|
|
27
|
|
|
|
|
1447
|
|
16
|
27
|
|
|
27
|
|
153
|
use Mojo::Util; |
|
27
|
|
|
|
|
54
|
|
|
27
|
|
|
|
|
1077
|
|
17
|
26
|
|
|
26
|
|
13708
|
use Mandel::Model::Field; |
|
26
|
|
|
|
|
63
|
|
|
26
|
|
|
|
|
231
|
|
18
|
26
|
|
|
26
|
|
768
|
use Carp 'confess'; |
|
26
|
|
|
|
|
92
|
|
|
26
|
|
|
|
|
16315
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
my $ANON = 1; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head2 collection_name |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
The name of the collection in the database. Default is the plural form of L. |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head2 collection_class |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
The class name of the collection class. This default to L. |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head2 document_class |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
The class name of the document this description is attached to. Default to |
35
|
|
|
|
|
|
|
an autogenerated class name. |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
=head2 name |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
The name of this model. Same as given to L and |
40
|
|
|
|
|
|
|
L. |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=cut |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
has collection_name => sub { |
45
|
|
|
|
|
|
|
my $self = shift; |
46
|
|
|
|
|
|
|
my $name = $self->name; |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
return $name =~ /s$/ ? $name : $name . 's' if $name; |
49
|
|
|
|
|
|
|
confess "collection_name or name required in constructor"; |
50
|
|
|
|
|
|
|
}; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
has collection_class => 'Mandel::Collection'; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
has document_class => sub { |
55
|
|
|
|
|
|
|
my $self = shift; |
56
|
|
|
|
|
|
|
my $name = ucfirst $self->name || 'AnonDoc'; |
57
|
|
|
|
|
|
|
my $class = "Mandel::Document::__ANON_${ANON}__::$name"; # this might change |
58
|
|
|
|
|
|
|
|
59
|
5
|
|
|
5
|
|
30
|
eval <<" PACKAGE" or confess $@; |
|
5
|
|
|
5
|
|
10
|
|
|
5
|
|
|
1
|
|
23
|
|
|
5
|
|
|
4
|
|
28
|
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
20
|
|
|
1
|
|
|
|
|
33
|
|
|
4
|
|
|
|
|
108
|
|
60
|
|
|
|
|
|
|
package $class; |
61
|
|
|
|
|
|
|
use Mojo::Base "Mandel::Document"; |
62
|
|
|
|
|
|
|
sub model { \$self } |
63
|
|
|
|
|
|
|
\$INC{"Mandel/Document/__ANON__$ANON.pm"} = "GENERATED"; |
64
|
|
|
|
|
|
|
PACKAGE |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
$ANON++; |
67
|
|
|
|
|
|
|
$class; |
68
|
|
|
|
|
|
|
}; |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
has name => ''; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 METHODS |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=head2 field |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
$field_obj = $self->field('name'); |
77
|
|
|
|
|
|
|
$self = $self->field(name => \%meta); |
78
|
|
|
|
|
|
|
$self = $self->field(['name1', 'name2'], \%meta); |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Used to define new field(s) or retrieve a defined L |
81
|
|
|
|
|
|
|
object. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=cut |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
sub field { |
86
|
17
|
|
|
17
|
1
|
39
|
my ($self, $name, $meta) = @_; |
87
|
|
|
|
|
|
|
|
88
|
17
|
100
|
|
|
|
50
|
if ($meta) { |
89
|
12
|
|
|
|
|
37
|
return $self->_add_field($name => $meta); # $name might be an array-ref |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
5
|
50
|
|
|
|
6
|
for (@{$self->{fields} || []}) { |
|
5
|
|
|
|
|
21
|
|
93
|
15
|
100
|
|
|
|
37
|
return $_ if $name eq $_->name; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
0
|
|
|
|
|
0
|
return; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub _add_field { |
100
|
12
|
|
|
12
|
|
24
|
my ($self, $fields, $meta) = @_; |
101
|
12
|
|
|
|
|
48
|
my $class = $self->document_class; |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Compile fieldibutes |
104
|
12
|
100
|
|
|
|
113
|
for my $name (@{ref $fields eq 'ARRAY' ? $fields : [$fields]}) { |
|
12
|
|
|
|
|
51
|
|
105
|
13
|
|
|
|
|
37
|
local $meta->{name} = $name; |
106
|
13
|
|
|
|
|
147
|
my $field = Mandel::Model::Field->new($meta); |
107
|
13
|
|
|
|
|
157
|
my $builder = $field->builder; |
108
|
13
|
|
|
|
|
36
|
my $code = ""; |
109
|
|
|
|
|
|
|
|
110
|
13
|
|
|
|
|
51
|
$code .= "package $class;\nsub $name {\n my \$raw = \$_[0]->data;\n"; |
111
|
|
|
|
|
|
|
|
112
|
13
|
100
|
|
|
|
34
|
if ($builder) { |
113
|
2
|
|
|
|
|
7
|
$code |
114
|
|
|
|
|
|
|
.= "return exists \$raw->{'$name'} ? (\$raw->{'$name'}) : (\$raw->{'$name'} = \$_[0]->\$builder) if \@_ == 1;\n"; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
else { |
117
|
11
|
|
|
|
|
28
|
$code .= "return \$raw->{'$name'} if \@_ == 1;\n"; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
13
|
|
|
|
|
21
|
$code .= "local \$_ = \$_[1];\n"; |
121
|
13
|
100
|
|
|
|
84
|
$code .= $self->_field_type($meta->{isa}) if $meta->{isa}; |
122
|
13
|
|
|
|
|
36
|
$code .= "\$_[0]->{dirty}{$name} = 1;"; |
123
|
13
|
|
|
|
|
27
|
$code .= "\$raw->{'$name'} = \$_;\n"; |
124
|
13
|
|
|
|
|
20
|
$code .= "return \$_[0];\n}"; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# We compile custom attribute code for speed |
127
|
26
|
|
|
26
|
|
144
|
no strict 'refs'; |
|
26
|
|
|
|
|
45
|
|
|
26
|
|
|
|
|
6506
|
|
128
|
13
|
50
|
|
|
|
42
|
warn "-- Attribute $name in $class\n$code\n\n" if $ENV{MOJO_BASE_DEBUG}; |
129
|
13
|
50
|
|
7
|
0
|
2190
|
Carp::croak "Mandel::Document error: $@ ($code)" unless eval "$code;1"; |
|
6
|
100
|
|
2
|
|
66
|
|
|
6
|
100
|
|
1
|
|
98
|
|
|
5
|
50
|
|
1
|
|
4740
|
|
|
3
|
50
|
|
1
|
|
60
|
|
|
3
|
50
|
|
|
|
8
|
|
|
3
|
50
|
|
|
|
9
|
|
|
4
|
50
|
|
|
|
35
|
|
|
3
|
|
|
|
|
62
|
|
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
901
|
|
|
2
|
|
|
|
|
67
|
|
|
2
|
|
|
|
|
10
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
5
|
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
9
|
|
|
1
|
|
|
|
|
32
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
1
|
|
|
|
|
511
|
|
|
1
|
|
|
|
|
34
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
|
131
|
13
|
|
|
|
|
43
|
push @{$self->{fields}}, $field; |
|
13
|
|
|
|
|
61
|
|
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
12
|
|
|
|
|
45
|
$self; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head2 fields |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
@fields = $self->fields; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
Get list of L objects in the order they were added to |
142
|
|
|
|
|
|
|
thie model. |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=cut |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub fields { |
147
|
4
|
100
|
|
4
|
1
|
75
|
@{$_[0]->{fields} || []}; |
|
4
|
|
|
|
|
49
|
|
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub _field_type { |
151
|
7
|
|
|
7
|
|
43
|
my ($self, $type) = @_; |
152
|
7
|
|
|
|
|
17
|
my $code = ""; |
153
|
|
|
|
|
|
|
|
154
|
26
|
|
|
26
|
|
23789
|
use Types::Standard qw( Num ); |
|
26
|
|
|
|
|
1857672
|
|
|
26
|
|
|
|
|
275
|
|
155
|
|
|
|
|
|
|
|
156
|
7
|
100
|
100
|
|
|
26
|
if ($type->has_coercion and $type->coercion->can_be_inlined) { |
157
|
3
|
|
|
|
|
113
|
$code .= '$_ = '.$type->coercion->inline_coercion('$_').";\n"; |
158
|
|
|
|
|
|
|
} |
159
|
7
|
100
|
|
|
|
355
|
if ($type->can_be_inlined) { |
160
|
7
|
|
|
|
|
135
|
$code .= $type->inline_assert('$_')."\n"; |
161
|
|
|
|
|
|
|
} |
162
|
8
|
100
|
|
|
|
390
|
if ($type->is_a_type_of(Num)) { |
163
|
5
|
|
|
|
|
376
|
$code .= "\$_ += 0;\n"; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
7
|
|
|
|
|
3769
|
return $code; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head2 relationship |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
$rel_obj = $self->relationship($type => $accessor => 'Other::Document::Class', %args); |
172
|
|
|
|
|
|
|
$rel_obj = $self->relationship($accessor); |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
This method is used to describe a relationship between two documents. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
See L, L or |
177
|
|
|
|
|
|
|
L. |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
C<$accessor> will be used as l, |
180
|
|
|
|
|
|
|
"Other::Document::Class" will be used as L |
181
|
|
|
|
|
|
|
and C will be used as |
182
|
|
|
|
|
|
|
L. |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
C<%args> is passed on the the L constructor. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub relationship { |
189
|
6
|
|
|
4
|
1
|
2968
|
my $self = shift; |
190
|
|
|
|
|
|
|
|
191
|
6
|
50
|
|
|
|
37
|
if (@_ == 1) { |
192
|
1
|
|
|
|
|
3
|
return $self->{relationship}{$_[0]}; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
|
195
|
5
|
|
|
|
|
17
|
my ($type, $field, $other, %args) = @_; |
196
|
5
|
|
|
|
|
30
|
my $class = 'Mandel::Relationship::' . Mojo::Util::camelize($type); |
197
|
5
|
|
|
|
|
99
|
my $e = load_class $class; |
198
|
|
|
|
|
|
|
|
199
|
4
|
100
|
|
|
|
69
|
confess $e if ref $e; |
200
|
|
|
|
|
|
|
|
201
|
4
|
|
|
|
|
23
|
$self->{relationship}{$field} |
202
|
|
|
|
|
|
|
= $class->new(accessor => $field, document_class => $self->document_class, related_class => $other, %args,); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head2 new_collection |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
$self->new_collection($connection); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Returns a new instance of L. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=cut |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
sub new_collection { |
214
|
3
|
|
|
5
|
1
|
19
|
my ($self, $connection, %args) = @_; |
215
|
|
|
|
|
|
|
|
216
|
3
|
|
100
|
|
|
13
|
$self->collection_class->new( |
217
|
|
|
|
|
|
|
{connection => $connection || confess('$model->new_collection($connection)'), model => $self, %args,}); |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
=head1 SEE ALSO |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
L, L, L |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head1 AUTHOR |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
Jan Henning Thorsen - C |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=cut |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
1; |