/[cvs]/nfo/perl/libs/Class/Tangram-1.12.pm
ViewVC logotype

Contents of /nfo/perl/libs/Class/Tangram-1.12.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Thu Oct 17 02:34:45 2002 UTC (21 years, 6 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
+ Class::Tangram 1.12

1 package Class::Tangram;
2
3 # Copyright (c) 2001, 2002 Sam Vilain. All right reserved. This file
4 # is licensed under the terms of the Perl Artistic license.
5
6 =head1 NAME
7
8 Class::Tangram - create constructors, accessor and update methods for
9 objects from a Tangram-compatible object specification.
10
11 =head1 SYNOPSIS
12
13 package MyObject;
14
15 use base qw(Class::Tangram);
16
17 our $fields => { int => [ qw(foo bar) ],
18 string => [ qw(baz quux) ] };
19
20 package main;
21
22 my $object = MyObject->new(foo => 2, baz => "hello");
23
24 print $object->baz(); # prints "hello"
25
26 $object->set_quux("Something");
27
28 $object->set_foo("Something"); # dies - not an integer
29
30 =head1 DESCRIPTION
31
32 Class::Tangram is a tool for defining objects attributes. Simply
33 define your object's fields/attributes using the same syntax
34 introduced in _A Guided Tour of Tangram_, and you get objects that
35 work As You'd Expect(tm).
36
37 Class::Tangram has no dependancy upon Tangram, and vice versa.
38 Neither requires anything special of your objects, nor do they insert
39 any special fields into your objects. This is a very important
40 feature with innumerable benefits, and few (if any) other object
41 persistence tools have this feature.
42
43 So, fluff aside, let's run through how you use Class::Tangram to make
44 objects.
45
46 First, you decide upon the attributes your object is going to have.
47 You might do this using UML, or you might pick an existing database
48 table and declare each column to be an attribute (you can leave out
49 "id"; that one is implicit).
50
51 Your object should use Class::Tangram as a base class;
52
53 use base qw(Class::Tangram)
54
55 or for older versions of perl:
56
57 use Class::Tangram;
58 use vars qw(@ISA);
59 @ISA = qw(Class::Tangram)
60
61 You should then define a C<$fields> variable in the scope of the
62 package, that is a B<hash> from attribute B<types> (see
63 L<Tangram::Type>) to either an B<array> of B<attribute names>, or
64 another B<hash> from B<attribute names> to B<options hashes> (or
65 C<undef>). The layout of this structure coincides with the C<fields>
66 portion of a tangram schema (see L<Tangram::Schema>). Note: the term
67 `schema' is used frequently to refer to the C<$fields> structure.
68
69 For example,
70
71 package MyObject;
72 use base qw(Class::Tangram);
73
74 our $fields = {
75 int => {
76 juiciness => undef,
77 segments => {
78 # this code reference is called when this
79 # attribute is set, to check the value is
80 # OK
81 check_func => sub {
82 die "too many segments"
83 if (${(shift)} > 30);
84 },
85 # the default for this attribute.
86 init_default => 7,
87 },
88 },
89 ref => {
90 grower => undef,
91 },
92
93 # 'required' attributes - insist that these fields are
94 # set, both with constructor and set()/set_X methods
95 string => {
96 # true: 'type' must have non-empty value (for
97 # strings) or be logically true (for other types)
98 type => { required => 1 },
99
100 # false: 'tag' must be defined but may be empty
101 tag => { required => '' },
102 },
103
104 # fields allowed by Class::Tangram but not ever
105 # stored by Tangram - no type checking by default
106 transient => [ qw(_tangible) ],
107 };
108
109 It is of critical importance to your sanity that you understand how
110 anonymous hashes and anonymous arrays work in Perl. Some additional
111 features are used above that have not yet been introduced, but you
112 should be able to look at the above data structure and see that it
113 satisfies the conditions stated in the paragraph before it. If it is
114 hazy, I recommend reading L<perlref> or L<perlreftut>.
115
116 When the schema for the object is first imported (see L<Schema
117 import>), Class::Tangram defines accessor functions for each of the
118 attributes defined in the schema. These accessor functions are then
119 available as C<$object-E<gt>function> on created objects. By virtue
120 of inheritance, various other methods are available.
121
122 From Class::Tangram 1.12 onwards, no use of perl's C<AUTOLOAD>
123 functionality is used.
124
125 =cut
126
127 use strict;
128 use Carp qw(croak cluck);
129
130 use vars qw($VERSION %defaults);
131
132 use Set::Object;
133
134 use Pod::Constants -trim => 1,
135 'MODULE RELEASE' => sub { ($VERSION) = /(\d+\.\d+)/ },
136 'Default Type Checking' => sub { %defaults = eval; };
137
138 # $types{$class}->{$attribute} is the tangram type of each attribute
139 my (%types);
140
141 # $attribute_options{$class}->{$attribute} is the hash passed to tangram
142 # for the given attribute
143 my (%attribute_options);
144
145 # $check{$class}->{$attribute}->($value) is a function that will die
146 # if $value is not alright, see check_X functions
147 my (%check);
148
149 # Destructors for each attribute. They are called as
150 # $cleaners{$class}->{$attribute}->($self, $attribute);
151 my (%cleaners);
152
153 # init_default values for each attribute. These could be hash refs,
154 # array refs, code refs, or simple scalars. They will be stored as
155 # $init_defaults{$class}->{$attribute}
156 my (%init_defaults);
157
158 # $required_attributes{$class}->{$attribute} records which attributes
159 # are required... used only by new() at present.
160 my (%required_attributes);
161
162 # if a class is abstract, complain if one is constructed.
163 my (%abstract);
164
165 =head1 METHODS
166
167 The following methods are available for all Class::Tangram objects
168
169 =head2 Constructor
170
171 A Constructor is a method that returns a new instance of an object.
172
173 =over 4
174
175 =item Class-E<gt>new (attribute1 =E<gt> value, attribute2 =E<gt> value)
176
177 Sets up a new object of type C<Class>, with attributes set to the
178 values supplied.
179
180 Can also be used as an object method (normal use is as a "class
181 method"), in which case it returns a B<copy> of the object, without
182 any deep copying.
183
184 =cut
185
186 sub new ($@)
187 {
188 my $invocant = shift;
189 my $class = ref $invocant || $invocant;
190
191 (my @values, @_) = @_;
192
193 # Setup the object
194 my $self = { };
195 bless $self, $class;
196
197 # auto-load schema as necessary
198 exists $types{$class} or import_schema($class);
199
200 croak "Attempt to instantiate an abstract type"
201 if ($abstract{$class});
202
203 if (ref $invocant)
204 {
205 # The copy constructor; this could be better :)
206 # this has the side effect of much auto-vivification.
207 %$self = %$invocant;
208 $self->set (@values); # override with @values
209 }
210 else
211 {
212 $self->set (@values); # start with @values
213 }
214
215 $self->_fill_init_default();
216 $self->_check_required();
217
218 return $self;
219
220 }
221
222 sub _fill_init_default {
223 my $self = shift;
224 my $class = ref $self or die "_fill_init_default usage error";
225
226 # fill in fields that have defaults
227 while ( my ($attribute, $default) =
228 each %{$init_defaults{$class}} ) {
229
230 next if (exists $self->{$attribute});
231
232 my $setter = "set_$attribute";
233 if (ref $default eq "CODE") {
234 # sub { }, attribute gets return value
235 $self->$setter( $default->($self) );
236
237 } elsif (ref $default eq "HASH") {
238 # hash ref, copy hash
239 $self->$setter( { %{ $default } } );
240
241 } elsif (ref $default eq "ARRAY") {
242 # array ref, copy array
243 $self->$setter( [ @{ $default } ] );
244
245 } else {
246 # something else, an object or a scalar
247 $self->$setter($default);
248 }
249 }
250 }
251
252 sub _check_required {
253 my $self = shift;
254 my $class = ref $self;
255
256 # make sure field is not undef if 'required' option is set
257 if (my $required = $required_attributes{$class}) {
258
259 # find the immediate caller outside of this package
260 my $i = 0;
261 $i++ while UNIVERSAL::isa($self, scalar(caller($i))||";->");
262
263 # give Tangram some lenience - it is exempt from the effects
264 # of the "required" option
265 unless ( caller($i) =~ m/^Tangram::/ ) {
266 my @missing;
267 while ( my ($attribute, $value) = each %$required ) {
268 push(@missing, $attribute)
269 if ! exists $self->{$attribute};
270 }
271 croak("object missing required attribute(s): "
272 .join(', ',@missing).'.') if @missing;
273 }
274 }
275 }
276
277 =back
278
279 =head2 Accessing & Setting Attributes
280
281 =over
282
283 =item $instance->set(attribute => $value, ...)
284
285 Sets the attributes of the given instance to the given values. croaks
286 if there is a problem with the values.
287
288 This function simply calls C<$instance-E<gt>set_attribute($value)> for
289 each of the C<attribute =E<gt> $value> pairs passed to it.
290
291 =cut
292
293 sub set {
294 my $self = shift;
295
296 # yes, this is a lot to do. yes, it's slow. But I'm fairly
297 # certain that this could be handled efficiently if it were to be
298 # moved inside the Perl interpreter or an XS module
299 UNIVERSAL::isa($self, "Class::Tangram") or croak "type mismatch";
300 my $class = ref $self;
301 exists $check{$class} or import_schema($class);
302 croak "set must be called with an even number of arguments"
303 if (scalar(@_) & 1);
304
305 while (my ($name, $value) = splice @_, 0, 2) {
306
307 my $setter = "set_".$name;
308
309 croak "attempt to set an illegal field $name in a $class"
310 unless $self->can($setter);
311
312 $self->$setter($value);
313 }
314 }
315
316 =item $instance->get("attribute")
317
318 Gets the value of C<$attribute>. This simply calls
319 C<$instance-E<gt>get_attribute>. If multiple attributes are listed,
320 then a list of the attribute values is returned in order. Note that
321 you get back the results of the scalar context C<get_attribute> call
322 in this case.
323
324 =cut
325
326 sub get {
327 my $self = shift;
328 croak "get what?" unless @_;
329 UNIVERSAL::isa($self, "Class::Tangram") or croak "type mismatch";
330
331 my $class = ref $self;
332 exists $check{$class} or import_schema($class);
333
334 my $multiget = (scalar(@_) != 1);
335
336 my @return;
337 while ( my $field = shift ) {
338 my $getter = "get_".$field;
339 croak "attempt to read an illegal field $field in a $class"
340 unless $self->can($getter);
341
342 if ( $multiget ) {
343 push @return, scalar($self->$getter());
344 } else {
345 return $self->$getter();
346 }
347 }
348
349 return @return;
350 }
351
352 =item $instance->attribute($value)
353
354 If C<$value> is not given, then
355 this is equivalent to C<$instance-E<gt>get_attribute>
356
357 If C<$value> is given, then this is equivalent to
358 C<$instance-E<gt>set_attribute($value)>. This usage issues a warning
359 if warnings are on; you should change your code to use the
360 set_attribute syntax for better readability. OO veterans will tell
361 you that for maintainability object method names should always be a
362 verb.
363
364 =item $instance->get_attribute
365
366 =item $instance->set_attribute($value)
367
368 The normative way of getting and setting attributes. If you wish to
369 override the behaviour of an object when getting or setting an
370 attribute, override these functions. They will be called when you use
371 C<$instance-E<gt>attribute>, C<$instance-E<gt>get()>, constructors,
372 etc.
373
374 =item $instance->attribute_includes(@objects)
375
376 =item $instance->attribute_insert(@objects)
377
378 =item $instance->attribute_size
379
380 =item $instance->attribute_clear
381
382 =item $instance->attribute_remove(@objects)
383
384 This suite of functions applies to attributes that are sets (C<iset>
385 or C<set>). It could in theory also apply generally to all
386 collections - ie also arrays (C<iarray> or C<array>), and hashes
387 (C<hash>, C<ihash>). This will be implemented subject to user demand.
388
389 =back
390
391 B<Note:> The above functions can be overridden, but they may not be
392 called with the C<$self-E<gt>SUPER::> superclass chaining method.
393 This is because they are not defined within the scope of
394 Class::Tangram, only your package.
395
396 =cut
397
398 =head1 ATTRIBUTE TYPE CHECKING
399
400 Class::Tangram provides type checking of attributes when attributes
401 are set - either using the default C<set_attribute> functions, or
402 created via the C<new> constructor.
403
404 The checking has default behaviour for each type of attribute (see
405 L<Default Type Checking>), and can be extended arbitrarily via a
406 per-attribute C<check_func>, described below. Critical attributes can
407 be marked as such with the C<required> flag.
408
409 The specification of this type checking is placed in the class schema,
410 in the per-attribute B<options hash>. This is a Class::Tangram
411 extension to the Tangram schema structure.
412
413 =over
414
415 =item check_func
416
417 A function that is called with a B<reference> to the new value in
418 C<$_[0]>. It should call C<die()> if the value is bad. Note that
419 this check_func will never be passed an undefined value; this is
420 covered by the "required" option, below.
421
422 In the example schema (above), the attribute C<segments> has a
423 C<check_func> that prevents setting the value to anything greater than
424 30. Note that it does not prevent you from setting the value to
425 something that is not an integer; if you define a C<check_func>, it
426 replaces the default.
427
428 =item required
429
430 If this option is set to a true value, then the attribute must be set
431 to a true value to pass type checking. For string attributes, this
432 means that the string must be defined and non-empty (so "0" is true).
433 For other attribute types, the normal Perl definition of logical truth
434 is used.
435
436 If the required option is defined but logically false, (ie "" or 0),
437 then the attribute must also be defined, but may be set to a logically
438 false value.
439
440 If the required option is undefined, then the attribute may be set to
441 an undefined value.
442
443 For integration with tangram, the C<new()> function has a special
444 hack; if it is being invoked from within Tangram, then the required
445 test is skipped.
446
447 =back
448
449 =head2 Other per-attribute options
450
451 Any of the following options may be inserted into the per-attribute
452 B<options hash>:
453
454 =over
455
456 =item init_default
457
458 This value specifies the default value of the attribute when
459 it is created with C<new()>. It is a scalar value, it is
460 copied to the fresh object. If it is a code reference, that
461 code reference is called and its return value inserted into
462 the attribute. If it is an ARRAY or HASH reference, then
463 that array or hash is COPIED into the attribute.
464
465 =item destroy_func
466
467 If anything special needs to happen to this attribute before the
468 object is destroyed (or when someone calls
469 C<$object-E<gt>clear_refs()>), then define this. It is called as
470 C<$sub-E<gt>($object, "attribute")>.
471
472 =back
473
474 =head2 Default Type Checking
475
476 # The following list is eval'ed from this documentation
477 # when Class::Tangram loads, and used as default attribute
478 # options for the specified types. So, eg, the default
479 # "init_default" for "set" types is a subroutine that
480 # returns a new Set::Object container.
481
482 # "parse" is special - it is passed the options hash given
483 # by the user and should return (\&check_func,
484 # \&destroy_func). This is how the magical string type
485 # checking is performed - see the entry for parse_string(),
486 # below.
487
488 int => { check_func => \&check_int },
489 real => { check_func => \&check_real },
490 string => { parse => \&parse_string },
491 ref => { check_func => \&check_obj,
492 destroy_func => \&destroy_ref },
493 array => { check_func => \&check_array,
494 destroy_func => \&destroy_array },
495 iarray => { check_func => \&check_array,
496 destroy_func => \&destroy_array },
497 flat_array => { check_func => \&check_flat_array },
498 set => { check_func => \&check_set,
499 destroy_func => \&destroy_set,
500 init_default => sub { Set::Object->new() } },
501 iset => { check_func => \&check_set,
502 destroy_func => \&destroy_set,
503 init_default => sub { Set::Object->new() } },
504 dmdatetime => { check_func => \&check_dmdatetime },
505 rawdatetime => { check_func => \&check_rawdatetime },
506 rawdate => { check_func => \&check_rawdate },
507 rawtime => { check_func => \&check_rawtime },
508 flat_hash => { check_func => \&check_flat_hash },
509 transient => { check_func => \&check_nothing },
510 hash => { check_func => \&check_hash,
511 destroy_func => \&destroy_hash,
512 get_func => \&get_hash },
513 perl_dump => { check_func => \&check_nothing }
514
515 =over
516
517 =item check_X (\$value)
518
519 This series of internal functions are built-in C<check_func> functions
520 defined for all of the standard Tangram attribute types.
521
522 =over
523
524 =item check_string
525
526 checks that the supplied value is less than 255 characters long.
527
528 =cut
529
530 sub check_string {
531 croak "string too long"
532 if (length ${$_[0]} > 255);
533 }
534
535 =item check_int
536
537 checks that the value is a (possibly signed) integer
538
539 =cut
540
541 my $int_re = qr/^-?\d+$/;
542 sub check_int {
543 croak "not an integer"
544 if (${$_[0]} !~ m/$int_re/o);
545 }
546
547 =item check_real
548
549 checks that the value is a real number, by stringifying it and
550 matching it against (C<m/^-?\d*(\.\d*)?(e-?\d*)?$/>). Inefficient?
551 Yes. Patches welcome.
552
553 =cut
554
555 my $real_re = qr/^-?\d*(\.\d*)?(e-?\d*)?$/;
556 sub check_real {
557 croak "not a real number"
558 if (${$_[0]} !~ m/$real_re/o);
559 }
560
561 =item check_obj
562
563 checks that the supplied variable is a reference to a blessed object
564
565 =cut
566
567 # this pattern matches a regular reference
568 my $obj_re = qr/^(?:HASH|ARRAY|SCALAR)?$/;
569 sub check_obj {
570 croak "not an object reference"
571 if ((ref ${$_[0]}) =~ m/$obj_re/o);
572 }
573
574 =item check_flat_array
575
576 checks that $value is a ref ARRAY and that all elements are unblessed
577 scalars. Does NOT currently check that all values are of the correct
578 type (int vs real vs string, etc)
579
580 =cut
581
582 sub check_flat_array {
583 croak "not a flat array"
584 if (ref ${$_[0]} ne "ARRAY");
585 croak "flat array may not contain references"
586 if (map { (ref $_ ? "1" : ()) } @{$_[0]});
587 }
588
589 =item check_array
590
591 checks that $value is a ref ARRAY, and that each element in the array
592 is a reference to a blessed object.
593
594 =cut
595
596 sub check_array {
597 croak "array attribute not passed an array ref"
598 if (ref ${$_[0]} ne "ARRAY");
599 for my $a (@{${$_[0]}}) {
600 croak "member in array not an object reference"
601 if ((ref $a) =~ m/$obj_re/o);
602 }
603 }
604
605 =item check_set
606
607 checks that $value->isa("Set::Object")
608
609 =cut
610
611 sub check_set {
612 croak "set type not passed a Set::Object"
613 unless (UNIVERSAL::isa(${$_[0]}, "Set::Object"));
614 }
615
616 =item check_rawdate
617
618 checks that $value is of the form YYYY-MM-DD, or YYYYMMDD, or YYMMDD.
619
620 =cut
621
622 # YYYY-MM-DD HH:MM:SS
623 my $rawdate_re = qr/^(?: \d{4}-\d{2}-\d{2}
624 | (?:\d\d){3,4}
625 )$/x;
626 sub check_rawdate {
627 croak "invalid SQL rawdate"
628 unless (${$_[0]} =~ m/$rawdate_re/o);
629 }
630
631 =item check_rawtime
632
633 checks that $value is of the form HH:MM(:SS)?
634
635 =cut
636
637 # YYYY-MM-DD HH:MM:SS
638 my $rawtime_re = qr/^\d{1,2}:\d{2}(?::\d{2})?$/;
639 sub check_rawtime {
640 croak "invalid SQL rawtime"
641 unless (${$_[0]} =~ m/$rawtime_re/o);
642 }
643
644 =item check_rawdatetime
645
646 checks that $value is of the form YYYY-MM-DD HH:MM(:SS)? (the time
647 and/or the date can be missing), or a string of numbers between 6 and
648 14 numbers long.
649
650 =cut
651
652 my $rawdatetime_re = qr/^(?:
653 # YYYY-MM-DD HH:MM:SS
654 (?: (?:\d{4}-\d{2}-\d{2}\s+)?
655 \d{1,2}:\d{2}(?::\d{2})?
656 | \d{4}-\d{2}-\d{2}
657 )
658 | # YYMMDD, etc
659 (?:\d\d){3,7}
660 )$/x;
661 sub check_rawdatetime {
662 croak "invalid SQL rawdatetime dude"
663 unless (${$_[0]} =~ m/$rawdatetime_re/o);
664 }
665
666 =item check_dmdatetime
667
668 checks that $value is of the form YYYYMMDDHH:MM:SS, or those allowed
669 for rawdatetime.
670
671 =cut
672
673 sub check_dmdatetime {
674 croak "invalid SQL rawdatetime dude"
675 unless (${$_[0]} =~ m/^\d{10}:\d\d:\d\d$|$rawdatetime_re/o);
676 }
677
678 =item check_flat_hash
679
680 checks that $value is a ref HASH and all values are scalars. Does NOT
681 currently check that all values are of the correct type (int vs real
682 vs string, etc)
683
684 =cut
685
686 sub check_flat_hash {
687 croak "not a hash"
688 unless (ref ${$_[0]} eq "HASH");
689 while (my ($k, $v) = each %${$_[0]}) {
690 croak "hash not flat"
691 if (ref $k or ref $v);
692 }
693 }
694
695 =item check_hash
696
697 checks that $value is a ref HASH, that every key in the hash is a
698 scalar, and that every value is a blessed object.
699
700 =cut
701
702 sub check_hash {
703 croak "not a hash"
704 unless (ref ${$_[0]} eq "HASH");
705 while (my ($k, $v) = each %${$_[0]}) {
706 croak "hash key not flat"
707 if (ref $k);
708 croak "hash value not an object"
709 if (ref $v !~ m/$obj_re/);
710 }
711 }
712
713 =item check_nothing
714
715 checks whether Australians like sport
716
717 =cut
718
719 sub check_nothing { }
720
721 =back
722
723 =item destroy_X ($instance, $attr)
724
725 Similar story with the check_X series of functions, these are called
726 during object destruction on every attribute that has a reference that
727 might need breaking. Note: B<these functions all assume that
728 attributes belonging to an object that is being destroyed may be
729 destroyed also>. In other words, do not allow distinct objects to
730 share Set::Object containers or hash references in their attributes,
731 otherwise when one gets destroyed the others will lose their data.
732
733 Available functions:
734
735 =over
736
737 =item destroy_array
738
739 empties an array
740
741 =cut
742
743 sub destroy_array {
744 my $self = shift;
745 my $attr = shift;
746 my $t = tied $self->{$attr};
747 @{$self->{$attr}} = ()
748 unless (defined $t and $t =~ m,Tangram::CollOnDemand,);
749 delete $self->{$attr};
750 }
751
752 =item destroy_set
753
754 Calls Set::Object::clear to clear the set
755
756 =cut
757
758 sub destroy_set {
759 my $self = shift;
760 my $attr = shift;
761
762 my $t = tied $self->{$attr};
763 return if (defined $t and $t =~ m,Tangram::CollOnDemand,);
764 if (ref $self->{$attr} eq "Set::Object") {
765 $self->{$attr}->clear;
766 }
767 delete $self->{$attr};
768 }
769
770 =item destroy_hash
771
772 empties a hash
773
774 =cut
775
776 sub destroy_hash {
777 my $self = shift;
778 my $attr = shift;
779 my $t = tied $self->{$attr};
780 %{$self->{$attr}} = ()
781 unless (defined $t and $t =~ m,Tangram::CollOnDemand,);
782 delete $self->{$attr};
783 }
784
785 =item destroy_ref
786
787 destroys a reference.
788
789 =cut
790
791 sub destroy_ref {
792 my $self = shift;
793 delete $self->{shift};
794 }
795
796 =back
797
798 =item parse_X ($attribute, { schema option })
799
800 Parses the schema option field, and returns one or two closures that
801 act as a check_X and a destroy_X function for the attribute.
802
803 This is currently a very ugly hack, parsing the SQL type definition of
804 an object. But it was bloody handy in my case for hacking this in
805 quickly. This is probably unmanagably unportable across databases;
806 but send me bug reports on it anyway, and I'll try and make the
807 parsers work for as many databases as possible.
808
809 This perhaps should be replaced by primitives that go the other way,
810 building the SQL type definition from a more abstract definition of
811 the type.
812
813 Available functions:
814
815 =over
816
817 =item parse_string
818
819 parses SQL types of:
820
821 =over
822
823 =cut
824
825 use vars qw($quoted_part $sql_list);
826
827 $quoted_part = qr/(?: \"([^\"]+)\" | \'([^\']+)\' )/x;
828 $sql_list = qr/\(\s*
829 (
830 $quoted_part
831 (?:\s*,\s* $quoted_part )*
832 ) \s*\)/x;
833
834 sub parse_string {
835
836 my $attribute = shift;
837 my $option = shift;
838
839 # simple case; return the check_string function. We don't
840 # need a destructor for a string so don't return one.
841 if (!$option->{sql}) {
842 return \&check_string;
843 }
844
845 =item CHAR(N), VARCHAR(N)
846
847 closure checks length of string is less than N characters
848
849 =cut
850
851 if ($option->{sql} =~ m/^\s*(?:var)?char\s*\(\s*(\d+)\s*\)/ix) {
852 my $max_length = $1;
853 return sub {
854 die "string too long for $attribute"
855 if (length ${$_[0]} > $max_length);
856 };
857
858 =item TINYBLOB, BLOB, LONGBLOB
859
860 checks max. length of string to be 255, 65535 or 16777215 chars
861 respectively. Also works with "TEXT" instead of "BLOB"
862
863 =cut
864
865 } elsif ($option->{sql} =~ m/^\s*(?:tiny|long|medium)?
866 (?:blob|text)/ix) {
867 my $max_length = ($1 ? ($1 eq "tiny"?255:2**24 - 1)
868 : 2**16 - 1);
869 return sub {
870 die "string too long for $attribute"
871 if (${$_[0]} and length ${$_[0]} > $max_length);
872 };
873
874 =item SET("members", "of", "set")
875
876 checks that the value passed is valid as a SQL set type, and that all
877 of the passed values are allowed to be a member of that set.
878
879 =cut
880
881 } elsif (my ($members) = $option->{sql} =~
882 m/^\s*set\s*$sql_list/oi) {
883
884 my %members;
885 $members{lc($1 || $2)} = 1
886 while ( $members =~ m/\G[,\s]*$quoted_part/cog );
887
888 return sub {
889 for my $x (split /\s*,\s*/, ${$_[0]}) {
890 croak ("SQL set badly formed or invalid member $x "
891 ." (SET" . join(",", keys %members). ")")
892 if (not exists $members{lc($x)});
893 }
894 };
895
896 =item ENUM("possible", "values")
897
898 checks that the value passed is one of the allowed values.
899
900 =cut
901
902 } elsif (my ($values) = $option->{sql} =~
903 m/^\s*enum\s*$sql_list/oi ) {
904
905 my %values;
906 $values{lc($1 || $2)} = 1
907 while ( $values =~ m/\G[,\s]*$quoted_part/gc);
908
909 return sub {
910 croak ("invalid enum value ${$_[0]} must be ("
911 . join(",", keys %values). ")")
912 if (not exists $values{lc(${$_[0]})});
913 }
914
915
916 } else {
917 die ("Please build support for your string SQL type in "
918 ."Class::Tangram (".$option->{sql}.")");
919 }
920 }
921
922 =back
923
924 =back
925
926 =back
927
928 =head2 Quick Object Dumping and Destruction
929
930 =over
931
932 =item $instance->quickdump
933
934 Quickly show the blessed hash of an object, without descending into
935 it. Primarily useful when you have a large interconnected graph of
936 objects so don't want to use the B<x> command within the debugger.
937 It also doesn't have the side effect of auto-vivifying members.
938
939 This function returns a string, suitable for print()ing. It does not
940 currently escape unprintable characters.
941
942 =cut
943
944 sub quickdump($) {
945 my $self = shift;
946
947 my $r = "REF ". (ref $self). "\n";
948 for my $k (sort keys %$self) {
949 $r .= (" $k => "
950 . (
951 tied $self->{$k}
952 || ( ref $self->{$k}
953 ? $self->{$k}
954 : "'".$self->{$k}."'" )
955 )
956 . "\n");
957 }
958 return $r;
959 }
960
961
962 =item $instance->DESTROY
963
964 This function ensures that all of your attributes have their
965 destructors called. It calls the destroy_X function for attributes
966 that have it defined, if that attribute exists in the instance that we
967 are destroying. It calls the destroy_X functions as destroy_X($self,
968 $k)
969
970 =cut
971
972 sub DESTROY($) {
973 my $self = shift;
974
975 my $class = ref $self;
976
977 # if no cleaners are known for this class, it hasn't been imported
978 # yet. Don't call import_schema, that would be a bad idea in a
979 # destructor.
980 exists $cleaners{$class} or return;
981
982 # for every attribute that is defined, and has a cleaner function,
983 # call the cleaner function.
984 for my $k (keys %$self) {
985 if (defined $cleaners{$class}->{$k} and exists $self->{$k}) {
986 $cleaners{$class}->{$k}->($self, $k);
987 }
988 }
989 $self->{_DESTROYED} = 1;
990 }
991
992 =item $instance->clear_refs
993
994 This clears all references from this object, ie exactly what DESTROY
995 normally does, but calling an object's destructor method directly is
996 bad form. Also, this function has no qualms with loading the class'
997 schema with import_schema() as needed.
998
999 This is useful for breaking circular references, if you know you are
1000 no longer going to be using an object then you can call this method,
1001 which in many cases will end up cleaning up most of the objects you
1002 want to get rid of.
1003
1004 However, it still won't do anything about Tangram's internal reference
1005 to the object, which must still be explicitly unlinked with the
1006 Tangram::Storage->unload method.
1007
1008 =cut
1009
1010 sub clear_refs($) {
1011 my $self = shift;
1012 my $class = ref $self;
1013
1014 exists $cleaners{$class} or import_schema($class);
1015
1016 # break all ref's, sets, arrays
1017 for my $k (keys %$self) {
1018 if (defined $cleaners{$class}->{$k} and exists $self->{$k}) {
1019 $cleaners{$class}->{$k}->($self, $k);
1020 }
1021 }
1022 $self->{_NOREFS} = 1;
1023 }
1024
1025 =back
1026
1027 =head1 FUNCTIONS
1028
1029 The following functions are not intended to be called as object
1030 methods.
1031
1032 =head2 Schema Import
1033
1034 our $fields = { int => [ qw(foo bar) ],
1035 string => [ qw(baz quux) ] };
1036
1037 # Version 1.115 and below compatibility:
1038 our $schema = {
1039 fields => { int => [ qw(foo bar) ],
1040 string => [ qw(baz quux) ] }
1041 };
1042
1043 =over
1044
1045 =item Class::Tangram::import_schema($class)
1046
1047 Parses a tangram object field list, in C<${"${class}::fields"}> (or
1048 C<${"${class}::schema"}-E<gt>{fields}> to the internal type information
1049 hashes. It will also define all of the attribute accessor and update
1050 methods in the C<$class> package.
1051
1052 Note that calling this function twice for the same class is not
1053 tested and may produce arbitrary results. Patches welcome.
1054
1055 =cut
1056
1057 sub import_schema($) { # Damn this function is long
1058 my $class = shift;
1059
1060 eval {
1061 my ($fields, $bases, $abstract);
1062 {
1063
1064 # Here, we go hunting around for their defined schema and
1065 # options
1066 no strict 'refs';
1067 local $^W=0;
1068 eval {
1069 $fields = (${"${class}::fields"} ||
1070 ${"${class}::schema"}->{fields});
1071 $abstract = (${"${class}::abstract"} ||
1072 ${"${class}::schema"}->{abstract});
1073 $bases = ${"${class}::schema"}->{bases};
1074 };
1075 if ( my @stack = @{"${class}::ISA"}) {
1076 # clean "bases" information from @ISA
1077 my %seen = map { $_ => 1 } $class, __PACKAGE__;
1078 $bases = [];
1079 while ( my $super = pop @stack ) {
1080 if ( defined ${"${super}::schema"}
1081 or defined ${"${super}::fields"} ) {
1082 push @$bases, $super;
1083 } else {
1084 push @stack, grep { !$seen{$_}++ }
1085 @{"${super}::ISA"};
1086 }
1087 }
1088 if ( !$fields and !@$bases ) {
1089 die ("No schema and no Class::Tangram "
1090 ."superclass for $class; define "
1091 ."${class}::fields!");
1092 }
1093 }
1094 }
1095
1096 # if this is an abstract type, do not allow it to be
1097 # instantiated
1098 if ($abstract) {
1099 $abstract{$class} = 1;
1100 }
1101
1102 # If there are any base classes, import them first so that the
1103 # check, cleaners and init_defaults can be inherited
1104 if (defined $bases) {
1105 (ref $bases eq "ARRAY")
1106 or die "bases not an array ref for $class";
1107
1108 # Note that the order of your bases is significant, that
1109 # is if you are using multiple iheritance then the later
1110 # classes override the earlier ones.
1111 for my $super ( @$bases ) {
1112 import_schema $super unless (exists $check{$super});
1113
1114 # copy each of the per-class configuration hashes to
1115 # this class as defaults.
1116 my ($k, $v);
1117
1118 # FIXME - this repetition of code is getting silly :)
1119 $types{$class}->{$k} = $v
1120 while (($k, $v) = each %{ $types{$super} } );
1121 $check{$class}->{$k} = $v
1122 while (($k, $v) = each %{ $check{$super} } );
1123 $cleaners{$class}->{$k} = $v
1124 while (($k, $v) = each %{ $cleaners{$super} } );
1125 $attribute_options{$class}->{$k} = $v
1126 while (($k, $v) = each %{ $attribute_options{$super} } );
1127 $init_defaults{$class}->{$k} = $v
1128 while (($k, $v) = each %{ $init_defaults{$super} } );
1129 $required_attributes{$class}->{$k} = $v
1130 while (($k, $v) = each %{ $required_attributes{$super} } );
1131 }
1132 }
1133
1134 # iterate over each of the *types* of fields (string, int, ref, etc.)
1135 while (my ($type, $v) = each %$fields) {
1136 if (ref $v eq "ARRAY") {
1137 $v = { map { $_, undef } @$v };
1138 }
1139 my $def = $defaults{$type};
1140
1141 # iterate each of the *attributes* of a particular type
1142 while (my ($attribute, $options) = each %$v) {
1143
1144 # this is what we are finding out about each attribute
1145 # $type is already set
1146 my ($default, $check_func, $required, $cleaner);
1147 # set defaults from what they give
1148 $options ||= {};
1149 if (ref $options eq "HASH" or
1150 UNIVERSAL::isa($options, 'Tangram::Type')) {
1151 ($check_func, $default, $required, $cleaner)
1152 = @{$options}{qw(check_func init_default
1153 required destroy_func)};
1154 }
1155
1156 # Fill their settings with info from defaults
1157 if (ref $def eq "HASH") {
1158
1159 # try to magically parse their options
1160 if ( $def->{parse} and !($check_func and $cleaner) ) {
1161 my @a = $def->{parse}->($attribute, $options);
1162 $check_func ||= $a[0];
1163 $cleaner ||= $a[1];
1164 }
1165
1166 # fall back to defaults for this class
1167 $check_func ||= $def->{check_func};
1168 $cleaner ||= $def->{destroy_func};
1169 $default = $def->{init_default} unless defined $default;
1170 }
1171
1172 # everything must be checked!
1173 die "No check function for ${class}\->$attribute (type $type)"
1174 unless (ref $check_func eq "CODE");
1175
1176 $types{$class}->{$attribute} = $type;
1177 $check{$class}->{$attribute} = $check_func;
1178 {
1179 no strict "refs";
1180 local ($^W) = 0;
1181
1182 # build an appropriate "get_attribute" method, and
1183 # define other per-type methods
1184 my ($get_closure, $set_closure);
1185
1186 # implement with closures for speed
1187 if ( $type =~ m/i?set/ ) {
1188
1189 # GET_$attribute (Set::Object)
1190 $get_closure = sub {
1191 my $self = shift;
1192 if ( !defined $self->{$attribute} ) {
1193 $self->{$attribute} = Set::Object->new();
1194 }
1195 my $set = $self->{$attribute};
1196 ( wantarray ? $set->members : $set )
1197 };
1198
1199 # and add a whole load of other functions too
1200 for my $set_method (qw(includes insert size clear
1201 remove)) {
1202
1203 # ${attribute}_includes, etc
1204 my $set_method_closure = sub {
1205 my $self = shift;
1206 $self->{$attribute} = Set::Object->new()
1207 unless defined $self->{$attribute};
1208 return $self->{$attribute}->$set_method(@_);
1209 };
1210 *{$class."::${attribute}_$set_method"} =
1211 $set_method_closure unless
1212 (defined &{$class."::${attribute}_$set_method"});
1213 }
1214
1215 } elsif ( $type =~ m/i?array/ ) {
1216
1217 # GET_$attribute (array)
1218 # allow array slices, and return whole array
1219 # in list context
1220 $get_closure = sub {
1221 my $array = ($_[0]->{$attribute} ||= []);
1222 shift;
1223 if ( @_ ) {
1224 @{$array}[@_];
1225 } else {
1226 ( wantarray ? @{ $array } : $array )
1227 }
1228 };
1229
1230 } elsif ( $type =~ m/i?hash/ ) {
1231 # GET_$attribute (hash)
1232 # allow hash slices, and return whole hash in
1233 # list context
1234 $get_closure = sub {
1235 my $hash = ($_[0]->{$attribute} ||= {});
1236 shift;
1237 if ( @_ ) {
1238 @{$hash}{@_}
1239 } else {
1240 ( wantarray ? %{ $hash } : $hash );
1241 }
1242 };
1243 } else {
1244 # GET_$attribute (scalar)
1245 # return value only
1246 $get_closure = sub { $_[0]->{$attribute}; };
1247 }
1248
1249 *{$class."::get_$attribute"} = $get_closure
1250 unless (defined &{$class."::get_$attribute"});
1251
1252 # SET_$attribute (all)
1253 my $checkit = \$check{$class}->{$attribute};
1254
1255 # required hack for strings - duplicate the code
1256 # to avoid the following string comparison for
1257 # every set
1258 if ( $type eq "string" ) {
1259 $set_closure = sub {
1260 my $self = shift;
1261 my $value = shift;
1262 eval {
1263 if ( defined $value and length $value ) {
1264 ${$checkit}->(\$value);
1265 } elsif ( $required ) {
1266 die "value is required"
1267 } elsif ( defined $required ) {
1268 die "value must be defined"
1269 unless defined $value;
1270 }
1271 };
1272 $@ && croak("value failed type check - ${class}->"
1273 ."set_$attribute('$value') ($@)");
1274 $self->{$attribute} = $value;
1275 };
1276 } else {
1277 $set_closure = sub {
1278 my $self = shift;
1279 my $value = shift;
1280 eval {
1281 if ( $value ) {
1282 ${$checkit}->(\$value);
1283 } elsif ( $required ) {
1284 die "value is required"
1285 } elsif ( defined $required ) {
1286 die "value must be defined"
1287 unless defined $value;
1288 }
1289 };
1290 $@ && croak("value failed type check - ${class}->"
1291 ."set_$attribute('$value') ($@)");
1292 $self->{$attribute} = $value;
1293 };
1294 }
1295
1296 # now export them into the caller's namespace
1297 my ($getter, $setter)
1298 = ("get_$attribute", "set_$attribute");
1299 *{$class."::$getter"} = $get_closure
1300 unless defined &{$class."::$getter"};
1301 *{$class."::$setter"} = $set_closure
1302 unless defined &{$class."::$setter"};
1303
1304 *{$class."::$attribute"} = sub {
1305 my $self = shift;
1306 if ( @_ ) {
1307 warn("The OO Police say change your call "
1308 ."to ->set_$attribute") if ($^W);
1309 #goto $set_closure; # NO! BAD!! :-)
1310 return $self->$setter(@_);
1311 } else {
1312 return $self->$getter(@_);
1313 #goto $get_closure;
1314 }
1315 } unless defined &{$class."::$attribute"};
1316 }
1317
1318 $cleaners{$class}->{$attribute} = $cleaner
1319 if (defined $cleaner);
1320 $init_defaults{$class}->{$attribute} = $default
1321 if (defined $default);
1322 $required_attributes{$class}->{$attribute} = $required
1323 if (defined $required);
1324 $attribute_options{$class}->{$attribute} =
1325 ( $options || {} );
1326 }
1327 }
1328 };
1329
1330 $@ && die "$@ while trying to import schema for $class";
1331 }
1332
1333 =back
1334
1335 =head2 Run-time type information
1336
1337 It is possible to access the data structures that Class::Tangram uses
1338 internally to verify attributes, create objects and so on.
1339
1340 This should be considered a B<HIGHLY EXPERIMENTAL> interface to
1341 B<INTERNALS> of Class::Tangram.
1342
1343 Class::Tangram keeps seven internal hashes:
1344
1345 =over
1346
1347 =item C<%types>
1348
1349 C<$types{$class}-E<gt>{$attribute}> is the tangram type of each attribute,
1350 ie "ref", "iset", etc. See L<Tangram::Type>.
1351
1352 =item C<%attribute_options>
1353
1354 C<$attribute_options{$class}-E<gt>{$attribute}> is the options hash
1355 for a given attribute.
1356
1357 =item C<%required_attributes>
1358
1359 C<$required_attributes{$class}-E<gt>{$attribute}> is the 'required'
1360 option setting for a given attribute.
1361
1362 =item C<%check>
1363
1364 C<$check{$class}-E<gt>{$attribute}> is a function that will be passed
1365 a reference to the value to be checked and either throw an exception
1366 (die) or return true.
1367
1368 =item C<%cleaners>
1369
1370 C<$attribute_options{$class}-E<gt>{$attribute}> is a reference to a
1371 destructor function for that attribute. It is called as an object
1372 method on the object being destroyed, and should ensure that any
1373 circular references that this object is involved in get cleared.
1374
1375 =item C<%abstract>
1376
1377 C<$abstract-E<gt>{$class}> is set if the class is abstract
1378
1379 =item C<%init_defaults>
1380
1381 C<$init_defaults{$class}-E<gt>{$attribute}> represents what an
1382 attribute is set to automatically if it is not specified when an
1383 object is created. If this is a scalar value, the attribute is set to
1384 the value. If it is a function, then that function is called (as a
1385 method) and should return the value to be placed into that attribute.
1386 If it is a hash ref or an array ref, then that structure is COPIED in
1387 to the new object. If you don't want that, you can do something like
1388 this:
1389
1390 [...]
1391 flat_hash => {
1392 attribute => {
1393 init_default => sub { { key => "value" } },
1394 },
1395 },
1396 [...]
1397
1398 Now, every new object will share the same hash for that attribute.
1399
1400 =back
1401
1402 There are currently four functions that allow you to access parts of
1403 this information.
1404
1405 =over
1406
1407 =item Class::Tangram::attribute_options($class)
1408
1409 Returns a hash ref to a data structure from attribute names to the
1410 option hash for that attribute.
1411
1412 =cut
1413
1414 sub attribute_options($) {
1415 my $class = shift;
1416 return $attribute_options{$class};
1417 }
1418
1419 =item Class::Tangram::attribute_types($class)
1420
1421 Returns a hash ref from attribute names to the tangram type for that
1422 attribute.
1423
1424 =cut
1425
1426 sub attribute_types($) {
1427 my $class = shift;
1428 return $types{$class};
1429 }
1430
1431 =item Class::Tangram::required_attributes($class)
1432
1433 Returns a hash ref from attribute names to the 'required' option setting for
1434 that attribute. May also be called as a method, as in
1435 C<$instance-E<gt>required_attributes>.
1436
1437 =cut
1438
1439 sub required_attributes($) {
1440 my $class = ref $_[0] || $_[0];
1441 return $required_attributes{$class};
1442 }
1443
1444 =item Class::Tangram::init_defaults($class)
1445
1446 Returns a hash ref from attribute names to the default intial values for
1447 that attribute. May also be called as a method, as in
1448 C<$instance-E<gt>init_defaults>.
1449
1450 =cut
1451
1452 sub init_defaults($) {
1453 my $class = ref $_[0] || $_[0];
1454 return $init_defaults{$class};
1455 }
1456
1457 =item Class::Tangram::known_classes
1458
1459 This function returns a list of all the classes that have had their
1460 object schema imported by Class::Tangram.
1461
1462 =cut
1463
1464 sub known_classes {
1465 return keys %types;
1466 }
1467
1468 =item Class::Tangram::is_abstract($class)
1469
1470 This function returns true if the supplied class is abstract.
1471
1472 =cut
1473
1474 sub is_abstract {
1475 my $class = shift;
1476 $class eq "Class::Tangram" && ($class = shift);
1477
1478 exists $cleaners{$class} or import_schema($class);
1479 }
1480
1481 =item Class->set_init_default(attribute => $value);
1482
1483 Sets the default value on an attribute for newly created "Class"
1484 objects, as if it had been declared with init_default. Can be called
1485 as a class or an instance method.
1486
1487 =cut
1488
1489 sub set_init_default {
1490 my $invocant = shift;
1491 my $class = ref $invocant || $invocant;
1492
1493 exists $init_defaults{$class} or import_schema($class);
1494
1495 while ( my ($attribute, $value) = splice @_, 0, 2) {
1496 $init_defaults{$class}->{$attribute} = $value;
1497 }
1498 }
1499
1500 =back
1501
1502 =cut
1503
1504 # a little embedded package
1505
1506 package Tangram::Transient;
1507
1508 BEGIN {
1509 eval "use base qw(Tangram::Type)";
1510 if ( $@ ) {
1511 # no tangram
1512 } else {
1513 $Tangram::Schema::TYPES{transient} = bless {}, __PACKAGE__;
1514 }
1515 }
1516
1517 sub coldefs { }
1518
1519 sub get_exporter { }
1520 sub get_importer { }
1521
1522 sub get_import_cols {
1523 # print "Get_import_cols:" , Dumper \@_;
1524 return ();
1525 }
1526
1527 =head1 SEE ALSO
1528
1529 L<Tangram::Schema>
1530
1531 B<A guided tour of Tangram, by Sound Object Logic.>
1532
1533 http://www.soundobjectlogic.com/tangram/guided_tour/fs.html
1534
1535 =head1 DEPENDENCIES
1536
1537 The following modules are required to be installed to use
1538 Class::Tangram:
1539
1540 Set::Object => 1.02
1541 Pod::Constants => 0.11
1542 Test::Simple => 0.18
1543 Date::Manip => 5.21
1544
1545 Test::Simple and Date::Manip are only required to run the test suite.
1546
1547 If you find Class::Tangram passes the test suite with earlier versions
1548 of the above modules, please send me an e-mail.
1549
1550 =head2 MODULE RELEASE
1551
1552 This is Class::Tangram version 1.12.
1553
1554 =head1 BUGS/TODO
1555
1556 There should be more functions for breaking loops; in particular, a
1557 standard function called C<drop_refs($obj)>, which replaces references
1558 to $obj with the appropriate C<Tangram::RefOnDemand> object so that an
1559 object can be unloaded via C<Tangram::Storage->unload()> and actually
1560 have a hope of being reclaimed. Another function that would be handy
1561 would be a deep "mark" operation for manual mark & sweep garbage
1562 collection.
1563
1564 Need to think about writing some functions using C<Inline> for speed.
1565 One of these days...
1566
1567 Allow C<init_default> values to be set in a default import function?
1568
1569 ie
1570
1571 use MyClassTangramObject -defaults => { foo => "bar" };
1572
1573 =head1 AUTHOR
1574
1575 Sam Vilain, <sam@vilain.net>
1576
1577 =head2 CREDITS
1578
1579 # Some modifications
1580 # Copyright © 2001 Micro Sharp Technologies, Inc., Vancouver, WA, USA
1581 # Author: Karl M. Hegbloom <karlheg@microsharp.com>
1582 # Perl Artistic Licence.
1583
1584 Many thanks to Charles Owens and David Wheeler for their feedback,
1585 ideas, patches and bug testing.
1586
1587 =cut
1588
1589 69;
1590
1591 __END__
1592
1593 # From old SYNOPSIS, I decided it was too long. A lot of
1594 # the information here needs to be re-integrated into the
1595 # POD.
1596
1597 package Project;
1598
1599 # here's where we build the individual object schemas into
1600 # a Tangram::Schema object, which the Tangram::Storage
1601 # class uses to know which tables and columns to find
1602 # objects.
1603 use Tangram::Schema;
1604
1605 # TIMTOWTDI - this is the condensed manpage version :)
1606 my $dbschema = Tangram::Schema->new
1607 ({ classes =>
1608 [ 'Orange' => { fields => $Orange::fields },
1609 'MyObject' => { fields => $MyObject::schema }, ]});
1610
1611 sub schema { $dbschema };
1612
1613 package main;
1614
1615 # See Tangram::Relational for instructions on using
1616 # "deploy" to create the database this connects to. You
1617 # only have to do this if you want to write the objects to
1618 # a database.
1619 use Tangram::Relational;
1620 my ($dsn, $u, $p);
1621 my $storage = Tangram::Relational->connect
1622 (Project->schema, $dsn, $u, $p);
1623
1624 # Create an orange
1625 my $orange = Orange->new(
1626 juiciness => 8,
1627 type => 'Florida',
1628 tag => '', # required
1629 );
1630
1631 # Store it
1632 $storage->insert($orange);
1633
1634 # This is how you get values out of the objects
1635 my $juiciness = $orange->juiciness;
1636
1637 # a "ref" must be set to a blessed object, any object
1638 my $grower = bless { name => "Joe" }, "Farmer";
1639 $orange->set_grower ($grower);
1640
1641 # these are all illegal - type checking is fairly strict
1642 my $orange = eval { Orange->new; }; print $@;
1643 eval { $orange->set_juiciness ("Yum"); }; print $@;
1644 eval { $orange->set_segments (31); }; print $@;
1645 eval { $orange->set_grower ("Mr. Nice"); }; print $@;
1646
1647 # Demonstrate some "required" functionality
1648 eval { $orange->set_type (''); }; print $@;
1649 eval { $orange->set_type (undef); }; print $@;
1650 eval { $orange->set_tag (undef); }; print $@;
1651
1652 # this works too, but is slower
1653 $orange->get( "juiciness" );
1654 $orange->set( juiciness => 123,
1655 segments => 17 );
1656
1657 # Re-configure init_default - make each new orange have a
1658 # random juiciness
1659 $orange->set_init_default( juiciness => sub { int(rand(45)) } );

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed