Commit | Line | Data |
fcec2383 |
1 | #!/usr/bin/perl |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Test::More tests => 63; |
7 | use Test::Exception; |
8 | |
9 | BEGIN { |
10 | use_ok('Moose'); |
11 | } |
12 | |
13 | BEGIN { |
14 | |
15 | package Newswriter::Meta::Instance; |
16 | use strict; |
17 | use warnings; |
18 | use Moose; |
19 | |
20 | use DBM::Deep; |
21 | |
22 | extends 'Moose::Meta::Instance'; |
23 | |
24 | { |
25 | my $instance_counter = -1; |
26 | |
27 | my $db = DBM::Deep->new({ |
28 | file => "newswriter.db", |
29 | autobless => 1 |
30 | }); |
31 | $db->{root} = [] unless exists $db->{root}; |
32 | |
33 | sub _get_db { $db } |
34 | sub _reload_db { |
35 | $db = DBM::Deep->new({ |
36 | file => "newswriter.db", |
37 | autobless => 1 |
38 | }) |
39 | } |
40 | |
41 | sub create_instance { |
42 | my $self = shift; |
43 | $instance_counter++; |
44 | $db->{root}->[$instance_counter] = {}; |
45 | |
46 | $self->bless_instance_structure({ |
47 | oid => $instance_counter, |
48 | instance => $db->{root}->[$instance_counter] |
49 | }); |
50 | } |
51 | |
52 | sub find_instance { |
53 | my ($self, $oid) = @_; |
54 | my $instance_struct = $db->{root}->[$oid]; |
55 | |
56 | $self->bless_instance_structure({ |
57 | oid => $oid, |
58 | instance => $instance_struct |
59 | }); |
60 | } |
61 | } |
62 | |
63 | sub get_instance_oid { |
64 | my ($self, $instance) = @_; |
65 | $instance->{oid}; |
66 | } |
67 | |
68 | sub clone_instance { |
69 | confess "&clone_instance is left as an exercise for the user"; |
70 | } |
71 | |
72 | sub get_slot_value { |
73 | my ($self, $instance, $slot_name) = @_; |
74 | return $instance->{instance}->{$slot_name}; |
75 | } |
76 | |
77 | sub set_slot_value { |
78 | my ($self, $instance, $slot_name, $value) = @_; |
79 | $instance->{instance}->{$slot_name} = $value; |
80 | } |
81 | |
82 | sub is_slot_initialized { |
83 | my ($self, $instance, $slot_name, $value) = @_; |
84 | exists $instance->{instance}->{$slot_name} ? 1 : 0; |
85 | } |
86 | |
87 | sub weaken_slot_value { |
88 | confess "Not sure how well DBM::Deep plays with weak refs, Rob says 'Writer a test'"; |
89 | } |
90 | |
91 | sub inline_slot_access { |
92 | my ($self, $instance, $slot_name) = @_; |
93 | sprintf "%s->{instance}->{%s}", $instance, $slot_name; |
94 | } |
95 | |
96 | package Newswriter::Meta::Class; |
97 | use strict; |
98 | use warnings; |
99 | use Moose; |
100 | |
101 | extends 'Moose::Meta::Class'; |
102 | |
103 | override 'construct_instance' => sub { |
104 | my ($class, %params) = @_; |
105 | return $class->get_meta_instance->find_instance($params{oid}) |
106 | if $params{oid}; |
107 | super(); |
108 | }; |
109 | } |
110 | |
111 | { |
112 | package Newswriter::Base; |
113 | use strict; |
114 | use warnings; |
115 | use metaclass 'Newswriter::Meta::Class' => ( |
116 | ':instance_metaclass' => 'Newswriter::Meta::Instance' |
117 | ); |
118 | use Moose; |
119 | |
120 | sub oid { |
121 | my $self = shift; |
122 | $self->meta |
123 | ->get_meta_instance |
124 | ->get_instance_oid($self); |
125 | } |
126 | |
127 | package Newswriter::Author; |
128 | use strict; |
129 | use warnings; |
130 | use metaclass 'Newswriter::Meta::Class' => ( |
131 | ':instance_metaclass' => 'Newswriter::Meta::Instance' |
132 | ); |
133 | use Moose; |
134 | |
135 | extends 'Newswriter::Base'; |
136 | |
137 | has 'first_name' => (is => 'rw', isa => 'Str'); |
138 | has 'last_name' => (is => 'rw', isa => 'Str'); |
139 | |
140 | package Newswriter::Article; |
141 | use strict; |
142 | use warnings; |
143 | use metaclass 'Newswriter::Meta::Class' => ( |
144 | ':instance_metaclass' => 'Newswriter::Meta::Instance' |
145 | ); |
146 | use Moose; |
147 | use Moose::Util::TypeConstraints; |
148 | |
149 | use DateTime::Format::MySQL; |
150 | |
151 | use base 'Newswriter::Base'; |
152 | |
153 | subtype 'Headline' |
154 | => as 'Str' |
155 | => where { length($_) < 100 }; |
156 | |
157 | subtype 'Summary' |
158 | => as 'Str' |
159 | => where { length($_) < 255 }; |
160 | |
161 | subtype 'DateTimeFormatString' |
162 | => as 'Str' |
163 | => where { DateTime::Format::MySQL->parse_datetime($_) }; |
164 | |
165 | enum 'Status' => qw(draft posted pending archive); |
166 | |
167 | has 'headline' => (is => 'rw', isa => 'Headline'); |
168 | has 'summary' => (is => 'rw', isa => 'Summary'); |
169 | has 'article' => (is => 'rw', isa => 'Str'); |
170 | |
171 | has 'start_date' => (is => 'rw', isa => 'DateTimeFormatString'); |
172 | has 'end_date' => (is => 'rw', isa => 'DateTimeFormatString'); |
173 | |
174 | has 'author' => (is => 'rw', isa => 'Newswriter::Author'); |
175 | |
176 | has 'status' => (is => 'rw', isa => 'Status'); |
177 | |
178 | around 'start_date', 'end_date' => sub { |
179 | my $c = shift; |
180 | my $self = shift; |
181 | $c->($self, DateTime::Format::MySQL->format_datetime($_[0])) if @_; |
182 | DateTime::Format::MySQL->parse_datetime($c->($self)); |
183 | }; |
184 | } |
185 | |
186 | { # check the meta stuff first |
187 | isa_ok(Newswriter::Base->meta, 'Newswriter::Meta::Class'); |
188 | isa_ok(Newswriter::Base->meta, 'Moose::Meta::Class'); |
189 | isa_ok(Newswriter::Base->meta, 'Class::MOP::Class'); |
190 | |
191 | is(Newswriter::Base->meta->instance_metaclass, |
192 | 'Newswriter::Meta::Instance', |
193 | '... got the right instance metaclass name'); |
194 | |
195 | isa_ok(Newswriter::Base->meta->get_meta_instance, 'Newswriter::Meta::Instance'); |
196 | |
197 | my $base = Newswriter::Base->new; |
198 | isa_ok($base, 'Newswriter::Base'); |
199 | isa_ok($base, 'Moose::Object'); |
200 | |
201 | isa_ok($base->meta, 'Newswriter::Meta::Class'); |
202 | isa_ok($base->meta, 'Moose::Meta::Class'); |
203 | isa_ok($base->meta, 'Class::MOP::Class'); |
204 | |
205 | is($base->meta->instance_metaclass, |
206 | 'Newswriter::Meta::Instance', |
207 | '... got the right instance metaclass name'); |
208 | |
209 | isa_ok($base->meta->get_meta_instance, 'Newswriter::Meta::Instance'); |
210 | } |
211 | |
212 | my $article_oid; |
213 | my $article_ref; |
214 | { |
215 | my $article; |
216 | lives_ok { |
217 | $article = Newswriter::Article->new( |
218 | headline => 'Home Office Redecorated', |
219 | summary => 'The home office was recently redecorated to match the new company colors', |
220 | article => '...', |
221 | |
222 | author => Newswriter::Author->new( |
223 | first_name => 'Truman', |
224 | last_name => 'Capote' |
225 | ), |
226 | |
227 | status => 'pending' |
228 | ); |
229 | } '... created my article successfully'; |
230 | isa_ok($article, 'Newswriter::Article'); |
231 | isa_ok($article, 'Newswriter::Base'); |
232 | |
233 | lives_ok { |
234 | $article->start_date(DateTime->new(year => 2006, month => 6, day => 10)); |
235 | $article->end_date(DateTime->new(year => 2006, month => 6, day => 17)); |
236 | } '... add the article date-time stuff'; |
237 | |
238 | ## check some meta stuff |
239 | |
240 | isa_ok($article->meta, 'Newswriter::Meta::Class'); |
241 | isa_ok($article->meta, 'Moose::Meta::Class'); |
242 | isa_ok($article->meta, 'Class::MOP::Class'); |
243 | |
244 | is($article->meta->instance_metaclass, |
245 | 'Newswriter::Meta::Instance', |
246 | '... got the right instance metaclass name'); |
247 | |
248 | isa_ok($article->meta->get_meta_instance, 'Newswriter::Meta::Instance'); |
249 | |
250 | ok($article->oid, '... got a oid for the article'); |
251 | |
252 | $article_oid = $article->oid; |
253 | $article_ref = "$article"; |
254 | |
255 | is($article->headline, |
256 | 'Home Office Redecorated', |
257 | '... got the right headline'); |
258 | is($article->summary, |
259 | 'The home office was recently redecorated to match the new company colors', |
260 | '... got the right summary'); |
261 | is($article->article, '...', '... got the right article'); |
262 | |
263 | isa_ok($article->start_date, 'DateTime'); |
264 | isa_ok($article->end_date, 'DateTime'); |
265 | |
266 | isa_ok($article->author, 'Newswriter::Author'); |
267 | is($article->author->first_name, 'Truman', '... got the right author first name'); |
268 | is($article->author->last_name, 'Capote', '... got the right author last name'); |
269 | |
270 | is($article->status, 'pending', '... got the right status'); |
271 | } |
272 | |
273 | Newswriter::Meta::Instance->_reload_db(); |
274 | |
275 | { |
276 | my $article; |
277 | lives_ok { |
278 | $article = Newswriter::Article->new(oid => $article_oid); |
279 | } '... (re)-created my article successfully'; |
280 | isa_ok($article, 'Newswriter::Article'); |
281 | isa_ok($article, 'Newswriter::Base'); |
282 | |
283 | is($article->oid, $article_oid, '... got a oid for the article'); |
284 | isnt($article_ref, "$article", '... got a new article instance'); |
285 | |
286 | is($article->headline, |
287 | 'Home Office Redecorated', |
288 | '... got the right headline'); |
289 | is($article->summary, |
290 | 'The home office was recently redecorated to match the new company colors', |
291 | '... got the right summary'); |
292 | is($article->article, '...', '... got the right article'); |
293 | |
294 | isa_ok($article->start_date, 'DateTime'); |
295 | isa_ok($article->end_date, 'DateTime'); |
296 | |
297 | isa_ok($article->author, 'Newswriter::Author'); |
298 | is($article->author->first_name, 'Truman', '... got the right author first name'); |
299 | is($article->author->last_name, 'Capote', '... got the right author last name'); |
300 | |
301 | lives_ok { |
302 | $article->author->first_name('Dan'); |
303 | $article->author->last_name('Rather'); |
304 | } '... changed the value ok'; |
305 | |
306 | is($article->author->first_name, 'Dan', '... got the changed author first name'); |
307 | is($article->author->last_name, 'Rather', '... got the changed author last name'); |
308 | |
309 | is($article->status, 'pending', '... got the right status'); |
310 | } |
311 | |
312 | Newswriter::Meta::Instance->_reload_db(); |
313 | |
314 | { |
315 | my $article; |
316 | lives_ok { |
317 | $article = Newswriter::Article->new(oid => $article_oid); |
318 | } '... (re)-created my article successfully'; |
319 | isa_ok($article, 'Newswriter::Article'); |
320 | isa_ok($article, 'Newswriter::Base'); |
321 | |
322 | is($article->oid, $article_oid, '... got a oid for the article'); |
323 | isnt($article_ref, "$article", '... got a new article instance'); |
324 | |
325 | is($article->headline, |
326 | 'Home Office Redecorated', |
327 | '... got the right headline'); |
328 | is($article->summary, |
329 | 'The home office was recently redecorated to match the new company colors', |
330 | '... got the right summary'); |
331 | is($article->article, '...', '... got the right article'); |
332 | |
333 | isa_ok($article->start_date, 'DateTime'); |
334 | isa_ok($article->end_date, 'DateTime'); |
335 | |
336 | isa_ok($article->author, 'Newswriter::Author'); |
337 | is($article->author->first_name, 'Dan', '... got the changed author first name'); |
338 | is($article->author->last_name, 'Rather', '... got the changed author last name'); |
339 | |
340 | is($article->status, 'pending', '... got the right status'); |
341 | } |
342 | |
343 | unlink('newswriter.db') if -e 'newswriter.db'; |