File Coverage

lib/Frost.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Frost;
2              
3 1     1   49239 use strict;
  1         2  
  1         22  
4 1     1   3 use warnings;
  1         1  
  1         18  
5              
6             # LIBS
7             #
8 1     1   504 use Moose ();
  1         303372  
  1         29  
9 1     1   7 use Moose::Exporter;
  1         2  
  1         6  
10              
11 1     1   543 use Frost::Types;
  0            
  0            
12             use Frost::Util ();
13              
14             use Frost::Meta::Class;
15             use Frost::Meta::Instance;
16             use Frost::Meta::Constructor;
17              
18             use Frost::Locum;
19              
20             # CLASS VARS
21             #
22             our $VERSION = '0.69_03';
23             $VERSION = eval $VERSION;
24              
25             our $AUTHORITY = 'cpan:ERNESTO';
26              
27             # CLASS INIT
28             #
29             Moose::Exporter->setup_import_methods ( also => 'Moose' );
30              
31             # CLASS METHODS
32             #
33              
34             #sub init_meta
35             #{
36             # shift; # just your package name
37             # my %options = @_;
38             #
39             # my $meta = Moose->init_meta
40             # (
41             # %options,
42             # base_class => 'Frost::Locum',
43             # );
44             #
45             # Moose::Util::MetaRole::apply_metaclass_roles
46             # (
47             # for_class => $options{for_class},
48             # metaclass_roles => [ 'Frost::Meta::Class' ],
49             # attribute_metaclass_roles => [ 'Frost::Meta::Attribute' ],
50             # instance_metaclass_roles => [ 'Frost::Meta::Instance' ],
51             # constructor_class_roles => [ 'Frost::Meta::Constructor' ],
52             # );
53             #
54             # return $meta;
55             #}
56              
57             sub init_meta
58             {
59             shift; # just your package name
60             my %options = @_;
61              
62             my $meta = Moose->init_meta
63             (
64             %options,
65             base_class => 'Frost::Locum',
66             );
67              
68             Moose::Util::MetaRole::apply_metaroles
69             (
70             for => $options{for_class},
71             class_metaroles =>
72             {
73             class => [ 'Frost::Meta::Class' ],
74             attribute => [ 'Frost::Meta::Attribute' ],
75             # method
76             # wrapped_method
77             instance => [ 'Frost::Meta::Instance' ],
78             constructor => [ 'Frost::Meta::Constructor' ],
79             # destructor
80             # error
81             }
82             );
83              
84             return $options{for_class}->meta();
85             }
86              
87             # PUBLIC ATTRIBUTES
88             #
89              
90             # PRIVATE ATTRIBUTES
91             #
92              
93             # CONSTRUCTORS
94             #
95              
96             # DESTRUCTORS
97             #
98              
99             # PUBLIC METHODS
100             #
101              
102             # PRIVATE METHODS
103             #
104              
105             # CALLBACKS
106             #
107              
108             # IMMUTABLE
109             #
110              
111             1;
112              
113             __END__
114              
115             =head1 NAME
116              
117             Frost - Feasible Referential Object STorage
118              
119             =head1 SYNOPSIS
120              
121             package My::BaseFoo;
122             # use Moose;
123             use Frost;
124              
125             has my_base_attr => ( ... );
126              
127             no Frost;
128             __PACKAGE__->meta->make_immutable(); # mutable is VERBOTEN
129              
130             ###################
131              
132             package My::Foo;
133             use Moose;
134             extends 'My::BaseFoo';
135              
136             use Frost::Util; # provides true() and false() aka 1 and 0
137              
138             has my_attr => ( ... );
139             has my_index_attr => ( index => true, ... );
140             has my_unique_attr => ( index => 'unique', ... );
141             has my_transient_attr => ( transient => true, ... );
142             has my_virtual_attr => ( virtual => true, ... );
143             has my_derived_attr => ( derived => true, ... );
144              
145             sub _build_my_derived_attr { ... }
146              
147             no Moose;
148             __PACKAGE__->meta->make_immutable(); # mutable is VERBOTEN
149              
150             ###################
151              
152             package My::Bar::AutoId;
153             use Moose;
154             extends 'My::Foo';
155              
156             use Frost::Util; # provides true() and false() aka 1 and 0
157              
158             has id => ( auto_id => true ); # UUID
159              
160             no Moose;
161             __PACKAGE__->meta->make_immutable();
162              
163             ###################
164              
165             package My::Bar::AutoInc;
166             use Moose;
167             extends 'My::Foo';
168              
169             use Frost::Util; # provides true() and false() aka 1 and 0
170              
171             has id => ( auto_inc => true ); # 1, 2, 3, 4, ....
172              
173             no Moose;
174             __PACKAGE__->meta->make_immutable();
175              
176             ###################
177              
178             package My::Loop;
179             use Moose;
180             extends 'My::BaseFoo';
181              
182             has next => ( isa => 'My::Loop', ... ) # weak ref is VERBOTEN
183             has last => ( isa => 'My::Loop', ... ) # weak ref is VERBOTEN
184              
185             no Moose;
186             __PACKAGE__->meta->make_immutable();
187              
188             ###################
189              
190             # application.cgi
191             #
192             use Frost::Asylum;
193             use My::Foo;
194             use My::Bar::AutoId;
195             use My::Bar::AutoInc;
196              
197             my $asylum = Frost::Asylum->new ( data_root => '/existing/path/for/my/data' );
198              
199             my ( $id_auto_id, $id_auto_inc );
200              
201             # Create
202             {
203             my $foo = My::Foo->new ( id => 42, asylum => $asylum, my_attr => ... );
204             my $bar_id = My::Bar::AutoId->new ( asylum => $asylum, my_attr => ... );
205             my $bar_inc = My::Bar::AutoInc->new ( asylum => $asylum, my_attr => ... );
206              
207             $id_auto_id = $bar_id->id; # something like ECDAEFD4-9247-11DE-9343-7794CBAD412D
208             $id_auto_inc = $bar_inc->id; # if empty 1, otherwise last used id + 1
209             }
210              
211             # Circular references
212             {
213             my $loop1 = My::Loop->new ( id => 'L1', asylum => $asylum );
214             my $loop2 = My::Loop->new ( id => 'L2', asylum => $asylum, last => $loop1 );
215             my $loop3 = My::Loop->new ( id => 'L3', asylum => $asylum, last => $loop2 );
216              
217             $loop1->last ( $loop3 );
218              
219             $loop1->next ( $loop2 );
220             $loop2->next ( $loop3 );
221             $loop3->next ( $loop1 );
222             }
223              
224             $asylum->close; # and auto-save
225              
226             # Evoke
227              
228             {
229             my $foo = My::Foo->new ( id => 42, asylum => $asylum );
230             my $bar_id = My::Bar::AutoId->new ( id => $id_auto_id, asylum => $asylum );
231             my $bar_inc = My::Bar::AutoInc->new ( id => $id_auto_inc, asylum => $asylum );
232              
233             my $loop2 = My::Loop->new ( id => 'L2', asylum => $asylum );
234              
235             ( $loop2->last->id eq 'L1' ) or die;
236             ( $loop2->next->id eq 'L3' ) or die;
237              
238             my $loop1 = $loop2->next->next;
239             }
240              
241             =head1 ABSTRACT
242              
243             Frost is an extension of Moose providing persistence even to circular structures.
244              
245             =head1 DESCRIPTION
246              
247             Once upon a time, when there were still real winters with frosty air,
248             an old moose named Elly Elk walked through the snow-white forest and
249             murmured over and over "How can I become persistent?", "I want to live
250             forever!" and more and more of that agonizing stuff.
251              
252             Suddenly she ran into Mona Moose, her old friend. Elly noticed, that
253             Mona was looking younger than ever, fresh and clean, although Mona was
254             as old as Elly. "How comes, that you're looking so fine?" Elly said
255             and Mona replied, that she would share her secret with Elly: "Come on,
256             join me at the Asylum."
257              
258             Said and done. The Asylum was a warm and cozy place and the warden was
259             a friendly man, although - with his peaked hat - he looked more like a
260             wizard. The room was dimly lit. Elly recognized many of her old
261             friends hanging out in the Twilight.
262              
263             "Yes, you can live forever as all the other moose, just sign here with
264             blood." the warden said.
265              
266             Elly Elk shivered but Mona Moose encouraged her: "This is a mere
267             formality."
268              
269             What the warden didn't tell, that he was a Necromancer and that behind
270             the Asylum was a big Cemetery, where his assistants - the Morticians -
271             did their clandestine work. But he knew, that - although he was
272             practicing only white magic - the truth would have frighten his
273             guests.
274              
275             "Trust me - I know what I'm doing!" he said and continued: "Look at
276             Mona and all your friends."
277              
278             So Elly Elk signed the registration form and the Necromancer blessed
279             her with an exclusive mantra and said: "With this mantra you'll be
280             unique in the world. As long as it's a known value, you'll live for
281             ever. But now take a sleep - you're looking tired."
282              
283             The Necromancer conducted Elly to his studio, where she was silenced.
284             And as she passed away, he removed her spirit and put it in the
285             Twilight zone.
286              
287             As he came back, Mona wanted to see Elly again. "That's easy!"
288             answered the Necromancer and with a little hex he evoked Elly and
289             turns her from a spirit to - no, not to the original Elly - but to a
290             confusingly similar Locum.
291              
292             "Welcome back, Elly!" Mona said, "You're looking so good now." And
293             really, Elly was feeling young and strong. Mona, Elly and all their
294             friends had much fun all day.
295              
296             In the evening the warden started to silence everybody - um, every
297             Locum - with the magic words "We've done a full day's work and it's
298             time for bed."
299              
300             When the Asylum was closed, the Necromancer absolved all spirits in
301             the Twilight and tasked the Morticians to extract the essence of every
302             spirit and bury it in the Cemetery while collecting every spirit's
303             mantra in a huge book called Illuminator.
304              
305             The next morning, when the Asylum was opened again. the Morticians
306             were instructed by the Necromancer to grub all essences from the
307             Cemetery. His secret assistents did as told: After consulting the
308             Illuminator, they aspirated every mantra to conjure up the spirit from
309             the essence. Then the Necromancer evoked every spirit and so the
310             lounge filled up with Locums again.
311              
312             So it went day in, day out. Elly and Mona and their friends were
313             persistent now and they all lived happily ever after.
314              
315             =head1 MOTIVATION
316              
317             =head2 Persistent storage even for circular structures like trees or loops is feasible
318              
319             As Matt Sergeant pointed out in his article at
320             L<http://www.perl.com/pub/a/2002/08/07/proxyobject.html> using
321             referential structures is problematic, because it leads often to
322             memory leakage.
323              
324             Weak references for object relations like Tree->parent and
325             Tree->children or Loop->next and Loop->last are no solution, because
326             at time the root object is leaving the scope, all references are lost
327             also.
328              
329             Using a proxy object as described in the article is bad too,
330             because deploying a tree constructed with a weak proxy will fail, if you
331             I<hold onto a sub-tree while letting the root of the tree go out of
332             scope. All of a sudden you'll find your data structure has become
333             untangled, like so much wool from a snagged jumper.> (Matt Sergeant)
334              
335             An AUTOLOAD solution would foil L<Moose>' fast immutable mode. Moreover
336             you always have to be sure, which attribute has to be weak or not - an
337             endless source of bugs.
338              
339             But we need referential structures - imagine a repertoire management
340             system for a theatre:
341              
342             We have productions (plays) bound to events (stage performances),
343             while any event points to a production and furthermore to a location,
344             each connected in turn to many productions. Moreover we have authors,
345             directors, technicians, actors etc. attached to events, locations and
346             productions and so on.
347              
348             Loops, loops, loops...
349              
350             The L<Moose> example in t/020_attributes/028_no_slot_access.t gave us the right direction.
351              
352             But just backending all attributes of a complete object - as in the
353             example - wouldn't provide us with a solution for circular references.
354             So why not deliver always a small proxy object (the
355             L<Locum|Frost::Locum>), which holds no real attributes in memory except
356             'id' (the mantra) and 'asylum' (the storage object
357             L<Asylum|Frost::Asylum>) for speed. Every other attribute is
358             kept in a cache (the L<Twilight|Frost::Twilight>) as a unique
359             hash structure (the spirit), which in turn is tied to a L<Berkeley
360             DB|DB_File> backend (the L<Cemetery|Frost::Cemetery>) managed
361             by the L<Necromancer|Frost::Necromancer> and his assistants,
362             the L<Morticians|Frost::Mortician>.
363              
364             Frost's meta voodoo provides us with a lightweight proxy mechanism
365             without AUTOLOAD tricks: Any other object is not stored in the owner
366             object's attribute as a real reference, but only as a special pointer
367             to the other already cached hash (aka spirit). Every time, the referenced
368             object is accessed, the factory (Asylum) delivers a new proxy object (Locum).
369             This way we'll never create hard circular references, which can't be
370             garbage collected.
371              
372             =head1 IMPLEMENTATION
373              
374             =head2 The underlying magic disclosed
375              
376             The program:
377              
378             # ===> next
379             # ---> last
380             #
381             # +---------+ +---------+
382             # | |====>| |
383             # | |<----| |
384             # | Loop(1) | | Loop(2) |
385             # | |---->| |
386             # | |<====| |
387             # +---------+ +---------+
388              
389             {
390             package Loop;
391             use Frost;
392             use Frost::Util; # provides true() and false() aka 1 and 0
393              
394             has content => ( is => 'rw', isa => 'Str' );
395              
396             has 'last' =>
397             (
398             is => 'rw',
399             isa => 'Loop',
400             weak_ref => false, # weak refs are VERBOTEN
401             );
402              
403             has 'next' =>
404             (
405             is => 'rw',
406             isa => 'Loop',
407             weak_ref => false, # weak refs are VERBOTEN
408             );
409              
410             sub add_next
411             {
412             my ( $self, $next ) = @_;
413              
414             $next->last ( $self );
415             $self->next ( $next );
416             }
417              
418             no Frost;
419              
420             __PACKAGE__->meta->make_immutable();
421             }
422              
423             use Frost::Asylum;
424              
425             my $asylum = Frost::Asylum->new ( data_root => '/existing/path/for/my/data' );
426              
427             my $loop1 = Loop->new ( asylum => $asylum, id => 1, content => 'This is Loop 1' );
428             my $loop2 = Loop->new ( asylum => $asylum, id => 2, content => 'This is Loop 2' );
429              
430             $loop1->add_next ( $loop2 );
431             $loop2->add_next ( $loop1 );
432              
433             gives us the structures (memory addresses simplified):
434              
435             Loop=HASH(100) ( = $loop1 )
436             {
437             id => 1,
438             asylum => Asylum=HASH(666),
439             _status => "missing",
440             }
441              
442             Loop=HASH(200) ( = $loop2 )
443             {
444             id => 2,
445             asylum => Asylum=HASH(666),
446             _status => "missing",
447             }
448              
449             Asylum=HASH(666)
450             {
451             twilight => Twilight=HASH(42)
452             {
453             'Loop|1' => { id => 1, _dirty => false,
454             content => 'This is Loop 1',
455             next => { type => 'Loop', ref => 2 }, last => { type => 'Loop', ref => 2 } },
456             'Loop|2' => { id => 2, _dirty => true,
457             content => 'This is Loop 2',
458             next => { type => 'Loop', ref => 1 }, last => { type => 'Loop', ref => 1 } },
459             }
460             }
461              
462             Loop 1 in the Twilight is NOT dirty as one may expect, because it was saved
463             automatically during silencing due to the referential structure.
464              
465             Somewhere else in the program:
466              
467             {
468             my $loop1n2 = $loop1->next();
469             my $loop1l2 = $loop1->last();
470              
471             my $loop2n1 = $loop2->next();
472             my $loop2l1 = $loop2->last();
473             }
474              
475             gives us the structures:
476              
477             Loop=HASH(300) ( = $loop1n2 )
478             {
479             id => 2,
480             asylum => Asylum=HASH(666),
481             _status => "exists",
482             }
483              
484             Loop=HASH(400) ( = $loop1l2 )
485             {
486             id => 2,
487             asylum => Asylum=HASH(666),
488             _status => "exists",
489             }
490              
491             Loop=HASH(500) ( = $loop2n1 )
492             {
493             id => 1,
494             asylum => Asylum=HASH(666),
495             _status => "exists",
496             }
497              
498             Loop=HASH(600) ( = $loop2l1 )
499             {
500             id => 1,
501             asylum => Asylum=HASH(666),
502             _status => "exists",
503             }
504              
505             The Twilight has not changed:
506              
507             Asylum=HASH(666)
508             {
509             twilight => Twilight=HASH(42)
510             {
511             'Loop|1' => { id => 1, _dirty => false,
512             content => 'This is Loop 1',
513             next => { type => 'Loop', ref => 2 }, last => { type => 'Loop', ref => 2 } },
514             'Loop|2' => { id => 2, _dirty => true,
515             content => 'This is Loop 2',
516             next => { type => 'Loop', ref => 1 }, last => { type => 'Loop', ref => 1 } },
517             }
518             }
519              
520             But we got new instances:
521              
522             Loop=HASH(300) != Loop=HASH(200)
523             Loop=HASH(400) != Loop=HASH(200)
524             Loop=HASH(500) != Loop=HASH(100)
525             Loop=HASH(600) != Loop=HASH(100)
526              
527             Continuing the program:
528              
529             my $loop3 = Loop->new ( asylum => $asylum, id => 3, content => 'This is Loop 3' );
530              
531             $loop1->add_next ( $loop3 );
532             $loop3->add_next ( $loop2 );
533              
534             gives us the structures:
535              
536             Loop=HASH(333) ( = $loop3 )
537             {
538             id => 3,
539             asylum => Asylum=HASH(666),
540             _status => "missing",
541             }
542              
543             Asylum=HASH(666)
544             {
545             twilight => Twilight=HASH(42)
546             {
547             'Loop|1' => { id => 1, _dirty => true,
548             content => 'This is Loop 1',
549             next => { type => 'Loop', ref => 3 }, last => { type => 'Loop', ref => 2 } },
550             'Loop|2' => { id => 2, _dirty => false,
551             content => 'This is Loop 2',
552             next => { type => 'Loop', ref => 1 }, last => { type => 'Loop', ref => 3 } },
553             'Loop|3' => { id => 3, _dirty => true,
554             content => 'This is Loop 3',
555             next => { type => 'Loop', ref => 2 }, last => { type => 'Loop', ref => 1 } },
556             }
557             }
558              
559             Now Loop 2 in the Twilight is NOT dirty, but the others. Which Locum
560             was automatically saved depends on the order of entering the
561             referential structure - adding to $loop3 first i.e.:
562              
563             $loop3->add_next ( $loop2 );
564             $loop1->add_next ( $loop3 );
565              
566             would yield:
567              
568             Asylum=HASH(666)
569             {
570             twilight => Twilight=HASH(42)
571             {
572             'Loop|1' => { id => 1, _dirty => true,
573             content => 'This is Loop 1',
574             next => { type => 'Loop', ref => 3 }, last => { type => 'Loop', ref => 2 } },
575             'Loop|2' => { id => 2, _dirty => false,
576             content => 'This is Loop 2',
577             next => { type => 'Loop', ref => 1 }, last => { type => 'Loop', ref => 3 } },
578             'Loop|3' => { id => 3, _dirty => false,
579             content => 'This is Loop 3',
580             next => { type => 'Loop', ref => 2 }, last => { type => 'Loop', ref => 1 } },
581             }
582             }
583              
584             But this doesn't matter, as long as you always close the Asylum. This
585             will auto-save all remaining dirty Loops:
586              
587             $asylum->close();
588              
589             What the user wanted:
590              
591             # ===> next
592             # ---> last
593             #
594             # +---------+ +---------+ +---------+
595             # | |====>| |====>| |
596             # | |<----| |<----| |
597             # | Loop(1) | | Loop(3) | | Loop(2) |
598             # | | | | | |
599             # | | | | | |
600             # | | | | | |
601             # | | | | | |
602             # | | +---------+ | |
603             # | |-------------------->| |
604             # | |<====================| |
605             # +---------+ +---------+
606              
607             could easily be reloaded - in another script the next day just say:
608              
609             my $loop3 = Loop->new ( id => 3, asylum => $asylum );
610              
611             print $loop3->content; # 'This is Loop 3'
612              
613             print $loop3->last->content; # 'This is Loop 1'
614             print $loop3->next->content; # 'This is Loop 2'
615             print $loop3->next->next->content; # 'This is Loop 1'
616             print $loop3->last->next->content; # 'This is Loop 3'
617              
618              
619             =head2 My friend Jack eats sugar lumps - more fun with attributes
620              
621             Frost comes with six new features extending L<Moose::Meta::Attribute>.
622              
623             They provide some sugar to deal with the location of an attribute,
624             to save some typing and to create indices.
625              
626             So migrating from a SQL database to an object-oriented storage is
627             possible without loosing one of the main features of a relational
628             database: indexing.
629              
630             =over 4
631              
632             =item transient
633              
634             has foo => ( transient => true, ... );
635              
636             A C<transient> attribute lives at run-time and is B<"local"> :
637              
638             It B<becomes undef>, when the Locum object goes B<out of scope>, and it's B<not saved>.
639              
640             =item virtual
641              
642             has bar => ( virtual => true, ... );
643              
644             A C<virtual> attribute lives at run-time and is B<"global"> :
645              
646             It's B<still present>, when the Locum object goes B<out of scope>, but it's B<not saved>.
647              
648             =item derived
649              
650             has dat => ( derived => true, ... );
651              
652             A C<derived> attribute lives at run-time and is B<"global"> :
653              
654             It's B<still present>, when the Locum object goes B<out of scope>, but it's B<not saved>.
655              
656             # The definition:
657              
658             has dat => ( derived => true, isa => 'Str' );
659              
660             # is a shortcut for:
661              
662             has dat => ( virtual => true, isa => 'Str', is => 'ro', init_arg => undef, lazy_build => true );
663              
664             # which becomes:
665              
666             has dat =>
667             (
668             virtual => true, # from derived
669             is => 'ro', #
670             init_arg => undef, #
671             isa => 'Str',
672             lazy => true, # from lazy_build
673             builder => '_build_dat', #
674             clearer => 'clear_dat', #
675             predicate => 'has_dat', #
676             );
677              
678             # and requires:
679              
680             sub _build_dat { ... }
681              
682             =item index
683              
684             package Foo;
685             ...
686             has foo => ( index => true, ... );
687             has bar => ( index => 'unique', ... );
688              
689             This creates a multiple or unique index
690             (L<Frost::Illuminator>) of the attribute values. Numeric sorting is automatically
691             determined from the attribute's C<isa>.
692              
693             Thus, if you create objects with following attributes:
694              
695             { id => 'id1', foo => 'foo1', bar => 'bar1' }
696             { id => 'id2', foo => 'foo2', bar => 'bar2' }
697             { id => 'id3', foo => 'foo3', bar => 'bar3' }
698             { id => 'id4', foo => 'foo3', bar => 'bar2' }
699             { id => 'id5', foo => 'foo1', bar => 'bar3' }
700              
701             you'll get two indices:
702              
703             foo1 -> id1
704             foo1 -> id5
705             foo2 -> id2
706             foo3 -> id3
707             foo3 -> id4
708              
709             bar1 -> id1
710             id2 silently eaten...
711             id3 silently eaten...
712             bar2 -> id4
713             bar3 -> id5
714              
715             Later you can search in the unique index:
716              
717             my $id = $asylum->find ( 'Foo', 'bar3', 'bar' ); # class, key, attribute_name
718              
719             # $id is 'id5'
720              
721             my $foo = Foo->new ( id => $id, asylum => $asylum );
722              
723             or iterate over the multiple index:
724              
725             my $id = $asylum->first ( 'Foo', 'foo1', 'foo' ); # class, key, attribute_name
726              
727             while ( $id )
728             # 1st loop: $id is 'id1'
729             # 2nd loop: $id is 'id5'
730             # 3rd loop: $id is ''
731             {
732             my $foo = Foo->new ( id => $id, asylum => $asylum );
733              
734             $id = $asylum->next ( 'Foo', 'foo1', 'foo' );
735             }
736              
737             and much more - see L<Frost::Asylum>.
738              
739             =item auto_id
740              
741             has id => ( auto_id => true, ... );
742             has +id => ( auto_id => true, ... );
743              
744             If the basic attribute B<id> is sweetened with C<auto_id>, the instance
745             is automatically assigned a UUID - see L<Data::UUID>.
746              
747             The resulting B<id> is something like C<ECDAEFD4-9247-11DE-9343-7794CBAD412D>.
748              
749             =item auto_inc
750              
751             has id => ( auto_inc => true, ... );
752             has +id => ( auto_inc => true, ... );
753              
754             If the basic attribute B<id> is sweetened with C<auto_inc>, the
755             instance is automatically assigned a sequential number: I<highest used
756             id> + 1, where I<highest used id> = 0 in an empty cemetery.
757              
758             =back
759              
760             See L<Frost::Meta::Attribute>
761              
762             =head1 The Four Commandments of Frost
763              
764             =head2 Thou shalt absolve no other Moose before Locum
765              
766             Frost can only store L<Moose> objects, more precisely: objects inheriting
767             from L<Frost::Locum>.
768              
769             This does not mean, that each of your old classes must now use
770             Frost instead of L<Moose>. Migrating is easily possible by
771             creating or changing a base class from C<use Moose> to C<use
772             Frost> - i.e.
773              
774             package My::BaseFoo;
775             # use Moose;
776             use Frost;
777              
778             no Frost;
779             __PACKAGE__->meta->make_immutable(); # mutable is VERBOTEN
780              
781             package My::Foo;
782             use Moose;
783             extends 'My::BaseFoo';
784              
785             has my_attr => ( ... );
786              
787             no Moose;
788             __PACKAGE__->meta->make_immutable(); # mutable is VERBOTEN
789              
790             Thus My::Foo and all inheriting classes can be defined the usual L<Moose>
791             way. The class My::BaseFoo inherits from Frost::Locum, pulling
792             in all its persistence stuff.
793              
794             =head2 Thou shalt honor immutability
795              
796             While applying L<Moose>' tests for Frost it appeared, that reblessing an
797             object - i.e. because of applying a role at run-time - creates mutable
798             objects blessed in an anonymous class. This destroys the silence/evoke
799             mechanism, which depends on the real classname.
800              
801             So reblessing as well as make_mutable is VERBOTEN.
802              
803             =head2 Thou shalt not weaken thy reference
804              
805             Due to Frost's proxy algorithm there is no need for weak references.
806             See L</MOTIVATION>.
807              
808             =head2 Thou shalt not create or load objects without an id and thy asylum
809              
810             To create a new frostable object you must always say:
811              
812             my $foo = Foo->new ( id => 'a_unique_id', asylum => $asylum, an_attr => ..., another_attr => ... );
813              
814             $remembered_id = $foo->id;
815              
816             And to reload a frosted object just say:
817              
818             my $foo = Foo->new ( id => $remembered_id, asylum => $asylum ); # other params ignored
819              
820             Or use the Asylum API - a matter of taste:
821              
822             my $remembered_id = 'a_unique_id';
823              
824             my $foo = $asylum->silence ( 'Foo', $remembered_id, an_attr => ..., another_attr => ... );
825              
826             # later...
827              
828             my $foo = $asylum->evoke ( 'Foo', $remembered_id ); # other params ignored
829              
830             If the C<id> is defined with C<auto_id> or C<auto_inc>, Asylum is creating a mantra for you - i.e.:
831              
832             package Bar;
833             ...
834             has id ( auto_id => 1 );
835             ...
836              
837             # Create and silence without id:
838             #
839             my $bar = Bar->new ( asylum => $asylum, an_attr => ..., another_attr => ... );
840              
841             my $bar_id = $bar->id; # something like ECDAEFD4-9247-11DE-9343-7794CBAD412D
842              
843             # Evoke with id:
844             #
845             my $bar = Bar->new ( id => $bar_id, asylum => $asylum );
846              
847             =head1 TODO
848              
849             Docs, docs, docs...
850              
851             =head1 GETTING HELP
852              
853             I'm reading the L<Moose> mailing list frequently, so please ask your
854             questions there.
855              
856             The mailing list is L<moose@perl.org>. You must be subscribed to send
857             a message. To subscribe, send an empty message to
858             L<moose-subscribe@perl.org>
859              
860             =head1 DEPENDENCIES
861              
862             This module requires these other modules and libraries:
863              
864             Carp
865             Class::MOP
866             Data::Dumper
867             Data::UUID
868             DB_File
869             Exporter
870             Fcntl
871             File::Path
872             IO::File
873             Log::Log4perl
874             Moose
875             Scalar::Util
876             Storable
877             Tie::Cache::LRU
878             Time::HiRes
879              
880             For testing these modules are needed:
881              
882             DateTime::Format::MySQL
883             List::Util
884             List::MoreUtils
885             Test::Deep
886             Test::Differences
887             Test::Exception
888             Test::More
889              
890             Optional modules to run some tests:
891              
892             Devel::Size
893             Sys::MemInfo
894             Declare::Constraints::Simple
895             Regexp::Common
896             Locale::US
897              
898             Please see Makefile.PL for required versions.
899              
900             =head1 BUGS
901              
902             All complex software has bugs lurking in it, and this module is no
903             exception.
904              
905             Please report any bugs to me or the mailing list.
906              
907             =head1 AUTHOR
908              
909             Ernesto L<ernesto@dienstleistung-kultur.de>
910              
911             =head1 COPYRIGHT AND LICENSE
912              
913             Copyright (C) 2010 by Dienstleistung Kultur Ltd. & Co. KG
914              
915             L<http://dienstleistung-kultur.de/frost/>
916              
917             This library is free software; you can redistribute it and/or modify
918             it under the same terms as Perl itself.
919              
920             =cut
921              
922