4db02f7ac4a8e1ac7fd157bcf48c6b1b3db6ad51
[gitmo/Mouse.git] / t / 200_examples / 002_example_Moose_POOP.t
1 #!/usr/bin/perl
2 # This is automatically generated by author/import-moose-test.pl.
3 # DO NOT EDIT THIS FILE. ANY CHANGES WILL BE LOST!!!
4 use t::lib::MooseCompat;
5
6 use strict;
7 use warnings;
8
9 use Test::More;
10
11 use Test::Requires {
12     'DBM::Deep' => '1.0003', # skip all if not installed
13     'DateTime::Format::MySQL' => '0.01',
14 };
15
16 use Test::Exception;
17
18 BEGIN {
19     # in case there are leftovers
20     unlink('newswriter.db') if -e 'newswriter.db';
21 }
22
23 END {
24     unlink('newswriter.db') if -e 'newswriter.db';
25 }
26
27
28 =pod
29
30 This example creates a very basic Object Database which
31 links in the instances created with a backend store
32 (a DBM::Deep hash). It is by no means to be taken seriously
33 as a real-world ODB, but is a proof of concept of the flexibility
34 of the ::Instance protocol.
35
36 =cut
37
38 BEGIN {
39
40     package Mouse::POOP::Meta::Instance;
41     use Mouse;
42
43     use DBM::Deep;
44
45     extends 'Mouse::Meta::Instance';
46
47     {
48         my %INSTANCE_COUNTERS;
49
50         my $db = DBM::Deep->new({
51             file      => "newswriter.db",
52             autobless => 1,
53             locking   => 1,
54         });
55
56         sub _reload_db {
57             #use Data::Dumper;
58             #warn Dumper $db;
59             $db = undef;
60             $db = DBM::Deep->new({
61                 file      => "newswriter.db",
62                 autobless => 1,
63                 locking   => 1,
64             });
65         }
66
67         sub create_instance {
68             my $self  = shift;
69             my $class = $self->associated_metaclass->name;
70             my $oid   = ++$INSTANCE_COUNTERS{$class};
71
72             $db->{$class}->[($oid - 1)] = {};
73
74             bless {
75                 oid      => $oid,
76                 instance => $db->{$class}->[($oid - 1)]
77             }, $class;
78         }
79
80         sub find_instance {
81             my ($self, $oid) = @_;
82             my $instance = $db->{$self->associated_metaclass->name}->[($oid - 1)];
83
84             bless {
85                 oid      => $oid,
86                 instance => $instance,
87             }, $self->associated_metaclass->name;
88         }
89
90         sub clone_instance {
91             my ($self, $instance) = @_;
92
93             my $class = $self->{meta}->name;
94             my $oid   = ++$INSTANCE_COUNTERS{$class};
95
96             my $clone = tied($instance)->clone;
97
98             bless {
99                 oid      => $oid,
100                 instance => $clone,
101             }, $class;
102         }
103     }
104
105     sub get_instance_oid {
106         my ($self, $instance) = @_;
107         $instance->{oid};
108     }
109
110     sub get_slot_value {
111         my ($self, $instance, $slot_name) = @_;
112         return $instance->{instance}->{$slot_name};
113     }
114
115     sub set_slot_value {
116         my ($self, $instance, $slot_name, $value) = @_;
117         $instance->{instance}->{$slot_name} = $value;
118     }
119
120     sub is_slot_initialized {
121         my ($self, $instance, $slot_name, $value) = @_;
122         exists $instance->{instance}->{$slot_name} ? 1 : 0;
123     }
124
125     sub weaken_slot_value {
126         confess "Not sure how well DBM::Deep plays with weak refs, Rob says 'Write a test'";
127     }
128
129     sub inline_slot_access {
130         my ($self, $instance, $slot_name) = @_;
131         sprintf "%s->{instance}->{%s}", $instance, $slot_name;
132     }
133
134     package Mouse::POOP::Meta::Class;
135     use Mouse;
136
137     extends 'Mouse::Meta::Class';
138
139     override '_construct_instance' => sub {
140         my $class = shift;
141         my $params = @_ == 1 ? $_[0] : {@_};
142         return $class->get_meta_instance->find_instance($params->{oid})
143             if $params->{oid};
144         super();
145     };
146
147 }
148 {
149     package Mouse::POOP::Object;
150     use metaclass 'Mouse::POOP::Meta::Class' => (
151         instance_metaclass => 'Mouse::POOP::Meta::Instance'
152     );
153     use Mouse;
154
155     sub oid {
156         my $self = shift;
157         $self->meta
158              ->get_meta_instance
159              ->get_instance_oid($self);
160     }
161
162 }
163 {
164     package Newswriter::Author;
165     use Mouse;
166
167     extends 'Mouse::POOP::Object';
168
169     has 'first_name' => (is => 'rw', isa => 'Str');
170     has 'last_name'  => (is => 'rw', isa => 'Str');
171
172     package Newswriter::Article;
173     use Mouse;
174     use Mouse::Util::TypeConstraints;
175
176     use DateTime::Format::MySQL;
177
178     extends 'Mouse::POOP::Object';
179
180     subtype 'Headline'
181         => as 'Str'
182         => where { length($_) < 100 };
183
184     subtype 'Summary'
185         => as 'Str'
186         => where { length($_) < 255 };
187
188     subtype 'DateTimeFormatString'
189         => as 'Str'
190         => where { DateTime::Format::MySQL->parse_datetime($_) };
191
192     enum 'Status' => qw(draft posted pending archive);
193
194     has 'headline' => (is => 'rw', isa => 'Headline');
195     has 'summary'  => (is => 'rw', isa => 'Summary');
196     has 'article'  => (is => 'rw', isa => 'Str');
197
198     has 'start_date' => (is => 'rw', isa => 'DateTimeFormatString');
199     has 'end_date'   => (is => 'rw', isa => 'DateTimeFormatString');
200
201     has 'author' => (is => 'rw', isa => 'Newswriter::Author');
202
203     has 'status' => (is => 'rw', isa => 'Status');
204
205     around 'start_date', 'end_date' => sub {
206         my $c    = shift;
207         my $self = shift;
208         $c->($self, DateTime::Format::MySQL->format_datetime($_[0])) if @_;
209         DateTime::Format::MySQL->parse_datetime($c->($self) || return undef);
210     };
211 }
212
213 { # check the meta stuff first
214     isa_ok(Mouse::POOP::Object->meta, 'Mouse::POOP::Meta::Class');
215     isa_ok(Mouse::POOP::Object->meta, 'Mouse::Meta::Class');
216     isa_ok(Mouse::POOP::Object->meta, 'Mouse::Meta::Class');
217
218     is(Mouse::POOP::Object->meta->instance_metaclass,
219       'Mouse::POOP::Meta::Instance',
220       '... got the right instance metaclass name');
221
222     isa_ok(Mouse::POOP::Object->meta->get_meta_instance, 'Mouse::POOP::Meta::Instance');
223
224     my $base = Mouse::POOP::Object->new;
225     isa_ok($base, 'Mouse::POOP::Object');
226     isa_ok($base, 'Mouse::Object');
227
228     isa_ok($base->meta, 'Mouse::POOP::Meta::Class');
229     isa_ok($base->meta, 'Mouse::Meta::Class');
230     isa_ok($base->meta, 'Mouse::Meta::Class');
231
232     is($base->meta->instance_metaclass,
233       'Mouse::POOP::Meta::Instance',
234       '... got the right instance metaclass name');
235
236     isa_ok($base->meta->get_meta_instance, 'Mouse::POOP::Meta::Instance');
237 }
238
239 my $article_oid;
240 my $article_ref;
241 {
242     my $article;
243     lives_ok {
244         $article = Newswriter::Article->new(
245             headline => 'Home Office Redecorated',
246             summary  => 'The home office was recently redecorated to match the new company colors',
247             article  => '...',
248
249             author => Newswriter::Author->new(
250                 first_name => 'Truman',
251                 last_name  => 'Capote'
252             ),
253
254             status => 'pending'
255         );
256     } '... created my article successfully';
257     isa_ok($article, 'Newswriter::Article');
258     isa_ok($article, 'Mouse::POOP::Object');
259
260     lives_ok {
261         $article->start_date(DateTime->new(year => 2006, month => 6, day => 10));
262         $article->end_date(DateTime->new(year => 2006, month => 6, day => 17));
263     } '... add the article date-time stuff';
264
265     ## check some meta stuff
266
267     isa_ok($article->meta, 'Mouse::POOP::Meta::Class');
268     isa_ok($article->meta, 'Mouse::Meta::Class');
269     isa_ok($article->meta, 'Mouse::Meta::Class');
270
271     is($article->meta->instance_metaclass,
272       'Mouse::POOP::Meta::Instance',
273       '... got the right instance metaclass name');
274
275     isa_ok($article->meta->get_meta_instance, 'Mouse::POOP::Meta::Instance');
276
277     ok($article->oid, '... got a oid for the article');
278
279     $article_oid = $article->oid;
280     $article_ref = "$article";
281
282     is($article->headline,
283        'Home Office Redecorated',
284        '... got the right headline');
285     is($article->summary,
286        'The home office was recently redecorated to match the new company colors',
287        '... got the right summary');
288     is($article->article, '...', '... got the right article');
289
290     isa_ok($article->start_date, 'DateTime');
291     isa_ok($article->end_date,   'DateTime');
292
293     isa_ok($article->author, 'Newswriter::Author');
294     is($article->author->first_name, 'Truman', '... got the right author first name');
295     is($article->author->last_name, 'Capote', '... got the right author last name');
296
297     is($article->status, 'pending', '... got the right status');
298 }
299
300 Mouse::POOP::Meta::Instance->_reload_db();
301
302 my $article2_oid;
303 my $article2_ref;
304 {
305     my $article2;
306     lives_ok {
307         $article2 = Newswriter::Article->new(
308             headline => 'Company wins Lottery',
309             summary  => 'An email was received today that informed the company we have won the lottery',
310             article  => 'WoW',
311
312             author => Newswriter::Author->new(
313                 first_name => 'Katie',
314                 last_name  => 'Couric'
315             ),
316
317             status => 'posted'
318         );
319     } '... created my article successfully';
320     isa_ok($article2, 'Newswriter::Article');
321     isa_ok($article2, 'Mouse::POOP::Object');
322
323     $article2_oid = $article2->oid;
324     $article2_ref = "$article2";
325
326     is($article2->headline,
327        'Company wins Lottery',
328        '... got the right headline');
329     is($article2->summary,
330        'An email was received today that informed the company we have won the lottery',
331        '... got the right summary');
332     is($article2->article, 'WoW', '... got the right article');
333
334     ok(!$article2->start_date, '... these two dates are unassigned');
335     ok(!$article2->end_date,   '... these two dates are unassigned');
336
337     isa_ok($article2->author, 'Newswriter::Author');
338     is($article2->author->first_name, 'Katie', '... got the right author first name');
339     is($article2->author->last_name, 'Couric', '... got the right author last name');
340
341     is($article2->status, 'posted', '... got the right status');
342
343     ## orig-article
344
345     my $article;
346     lives_ok {
347         $article = Newswriter::Article->new(oid => $article_oid);
348     } '... (re)-created my article successfully';
349     isa_ok($article, 'Newswriter::Article');
350     isa_ok($article, 'Mouse::POOP::Object');
351
352     is($article->oid, $article_oid, '... got a oid for the article');
353     isnt($article_ref, "$article", '... got a new article instance');
354
355     is($article->headline,
356        'Home Office Redecorated',
357        '... got the right headline');
358     is($article->summary,
359        'The home office was recently redecorated to match the new company colors',
360        '... got the right summary');
361     is($article->article, '...', '... got the right article');
362
363     isa_ok($article->start_date, 'DateTime');
364     isa_ok($article->end_date,   'DateTime');
365
366     isa_ok($article->author, 'Newswriter::Author');
367     is($article->author->first_name, 'Truman', '... got the right author first name');
368     is($article->author->last_name, 'Capote', '... got the right author last name');
369
370     lives_ok {
371         $article->author->first_name('Dan');
372         $article->author->last_name('Rather');
373     } '... changed the value ok';
374
375     is($article->author->first_name, 'Dan', '... got the changed author first name');
376     is($article->author->last_name, 'Rather', '... got the changed author last name');
377
378     is($article->status, 'pending', '... got the right status');
379 }
380
381 Mouse::POOP::Meta::Instance->_reload_db();
382
383 {
384     my $article;
385     lives_ok {
386         $article = Newswriter::Article->new(oid => $article_oid);
387     } '... (re)-created my article successfully';
388     isa_ok($article, 'Newswriter::Article');
389     isa_ok($article, 'Mouse::POOP::Object');
390
391     is($article->oid, $article_oid, '... got a oid for the article');
392     isnt($article_ref, "$article", '... got a new article instance');
393
394     is($article->headline,
395        'Home Office Redecorated',
396        '... got the right headline');
397     is($article->summary,
398        'The home office was recently redecorated to match the new company colors',
399        '... got the right summary');
400     is($article->article, '...', '... got the right article');
401
402     isa_ok($article->start_date, 'DateTime');
403     isa_ok($article->end_date,   'DateTime');
404
405     isa_ok($article->author, 'Newswriter::Author');
406     is($article->author->first_name, 'Dan', '... got the changed author first name');
407     is($article->author->last_name, 'Rather', '... got the changed author last name');
408
409     is($article->status, 'pending', '... got the right status');
410
411     my $article2;
412     lives_ok {
413         $article2 = Newswriter::Article->new(oid => $article2_oid);
414     } '... (re)-created my article successfully';
415     isa_ok($article2, 'Newswriter::Article');
416     isa_ok($article2, 'Mouse::POOP::Object');
417
418     is($article2->oid, $article2_oid, '... got a oid for the article');
419     isnt($article2_ref, "$article2", '... got a new article instance');
420
421     is($article2->headline,
422        'Company wins Lottery',
423        '... got the right headline');
424     is($article2->summary,
425        'An email was received today that informed the company we have won the lottery',
426        '... got the right summary');
427     is($article2->article, 'WoW', '... got the right article');
428
429     ok(!$article2->start_date, '... these two dates are unassigned');
430     ok(!$article2->end_date,   '... these two dates are unassigned');
431
432     isa_ok($article2->author, 'Newswriter::Author');
433     is($article2->author->first_name, 'Katie', '... got the right author first name');
434     is($article2->author->last_name, 'Couric', '... got the right author last name');
435
436     is($article2->status, 'posted', '... got the right status');
437
438 }
439
440 done_testing;