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