1Rose::DB::Object::HelpeUrsse(r3)Contributed Perl DocumenRtoastei:o:nDB::Object::Helpers(3)
2
3
4
6 Rose::DB::Object::Helpers - A mix-in class containing convenience
7 methods for Rose::DB::Object.
8
10 package MyDBObject;
11
12 use Rose::DB::Object;
13 our @ISA = qw(Rose::DB::Object);
14
15 use Rose::DB::Object::Helpers 'clone',
16 { load_or_insert => 'find_or_create' };
17 ...
18
19 $obj = MyDBObject->new(id => 123);
20 $obj->find_or_create();
21
22 $obj2 = $obj->clone;
23
25 Rose::DB::Object::Helpers provides convenience methods from use with
26 Rose::DB::Object-derived classes. These methods do not exist in
27 Rose::DB::Object in order to keep the method namespace clean. (Each
28 method added to Rose::DB::Object is another potential naming conflict
29 with a column accessor.)
30
31 This class inherits from Rose::Object::MixIn. See the
32 Rose::Object::MixIn documentation for a full explanation of how to
33 import methods from this class. The helper methods themselves are
34 described below.
35
37 Due to the "wonders" of Perl 5's object system, any helper method
38 described here can also be used as a Rose::DB::Object::Util-style
39 utility function that takes a Rose::DB::Object-derived object as its
40 first argument. Example:
41
42 # Import two helpers
43 use Rose::DB::Object::Helpers qw(clone_and_reset traverse_depth_first);
44
45 $o = My::DB::Object->new(...);
46
47 clone_and_reset($o); # Imported helper "method" called as function
48
49 # Imported helper "method" with arguments called as function
50 traverse_depth_first($o, handlers => { ... }, max_depth => 2);
51
52 Why, then, the distinction between Rose::DB::Object::Helpers methods
53 and Rose::DB::Object::Util functions? It's simply a matter of context.
54 The functions in Rose::DB::Object::Util are most useful in the context
55 of the internals (e.g., writing your own column method-maker) whereas
56 Rose::DB::Object::Helpers methods are most often added to a common
57 Rose::DB::Object-derived base class and then called as object methods
58 by all classes that inherit from it.
59
60 The point is, these are just conventions. Use any of these subroutines
61 as functions or as methods as you see fit. Just don't forget to pass a
62 Rose::DB::Object-derived object as the first argument when calling as a
63 function.
64
66 as_json [PARAMS]
67 Returns a JSON-formatted string created from the object tree as created
68 by the as_tree method. PARAMS are the same as for the as_tree method,
69 except that the "deflate" parameter is ignored (it is always set to
70 true).
71
72 You must have the JSON module version 2.12 or later installed in order
73 to use this helper method. If you have the JSON::XS module version
74 2.2222 or later installed, this method will work a lot faster.
75
76 as_tree [PARAMS]
77 Returns a reference to a hash of name/value pairs representing the
78 column values of this object as well as any nested sub-objects. The
79 PARAMS name/value pairs dictate the details of the sub-object
80 traversal. Valid parameters are:
81
82 allow_loops BOOL
83 If true, allow loops during the traversal (e.g., A -> B -> C -> A).
84 The default value is false.
85
86 deflate BOOL
87 If true, the values in the tree will be simple scalars suitable for
88 storage in the database (e.g., a date string like "2005-12-31"
89 instead of a DateTime object). The default is true.
90
91 exclude CODEREF
92 A reference to a subroutine that is called on each
93 Rose::DB::Object-derived object encountered during the traversal.
94 It is passed the object, the parent object (undef, if none), and
95 the Rose::DB::Object::Metadata::Relationship-derived object
96 (undef, if none) that led to this object. If the subroutine
97 returns true, then this object is not processed. Example:
98
99 exclude => sub
100 {
101 my($object, $parent, $rel_meta) = @_;
102 ...
103 return 1 if($should_exclude);
104 return 0;
105 },
106
107 force_load BOOL
108 If true, related sub-objects will be loaded from the database. If
109 false, then only the sub-objects that have already been loaded from
110 the database will be traversed. The default is false.
111
112 max_depth DEPTH
113 Do not descend past DEPTH levels. Depth is an integer starting
114 from 0 for the object that the as_tree method was called on and
115 increasing with each level of related objects. The default value
116 is 100.
117
118 persistent_columns_only BOOL
119 If true, non-persistent columns will not be included in the tree.
120 The default is false.
121
122 prune CODEREF
123 A reference to a subroutine that is called on each
124 Rose::DB::Object::Metadata::Relationship-derived object encountered
125 during traversal. It is passed the relationship object, the parent
126 object, and the depth. If the subroutine returns true, then the
127 entire sub-tree below this relationship will not be traversed.
128 Example:
129
130 prune => sub
131 {
132 my($rel_meta, $object, $depth) = @_;
133 ...
134 return 1 if($should_prune);
135 return 0;
136 },
137
138 Caveats: Currently, you cannot have a relationship and a column with
139 the same name in the same class. This should not happen without
140 explicit action on the part of the class creator, but it is technically
141 possible. The result of serializing such an object using as_tree is
142 undefined. This limitation may be removed in the future.
143
144 The exact format of the "tree" data structure returned by this method
145 is not public and may change in the future (e.g., to overcome the
146 limitation described above).
147
148 as_yaml [PARAMS]
149 Returns a YAML-formatted string created from the object tree as created
150 by the as_tree method. PARAMS are the same as for the as_tree method,
151 except that the "deflate" parameter is ignored (it is always set to
152 true).
153
154 You must have the YAML::Syck module installed in order to use this
155 helper method.
156
157 clone
158 Returns a new object initialized with the column values of the existing
159 object. For example, imagine a "Person" class with three columns,
160 "id", "name", and "age".
161
162 $a = Person->new(id => 123, name => 'John', age => 30);
163
164 This use of the "clone()" method:
165
166 $b = $a->clone;
167
168 is equivalent to this:
169
170 $b = Person->new(id => $a->id, name => $a->name, age => $a->age);
171
172 clone_and_reset
173 This is the same as the clone method described above, except that it
174 also sets all of the primary and unique key columns to undef. If the
175 cloned object has a db attribute, then it is copied to the clone object
176 as well.
177
178 For example, imagine a "Person" class with three columns, "id", "name",
179 and "age", where "id" is the primary key and "name" is a unique key.
180
181 $a = Person->new(id => 123, name => 'John', age => 30, db => $db);
182
183 This use of the "clone_and_reset()" method:
184
185 $b = $a->clone_and_reset;
186
187 is equivalent to this:
188
189 $b = Person->new(id => $a->id, name => $a->name, age => $a->age);
190 $b->id(undef); # reset primary key
191 $b->name(undef); # reset unique key
192 $b->db($a->db); # copy db
193
194 column_values_as_json
195 Returns a string containing a JSON representation of the object's
196 column values. You must have the JSON module version 2.12 or later
197 installed in order to use this helper method. If you have the JSON::XS
198 module version 2.2222 or later installed, this method will work a lot
199 faster.
200
201 column_values_as_yaml
202 Returns a string containing a YAML representation of the object's
203 column values. You must have the YAML::Syck module installed in order
204 to use this helper method.
205
206 column_accessor_value_pairs
207 Returns a hash (in list context) or reference to a hash (in scalar
208 context) of column accessor method names and column values. The keys
209 of the hash are the accessor method names for the columns. The values
210 are retrieved by calling the accessor method for each column.
211
212 column_mutator_value_pairs
213 Returns a hash (in list context) or reference to a hash (in scalar
214 context) of column mutator method names and column values. The keys of
215 the hash are the mutator method names for the columns. The values are
216 retrieved by calling the accessor method for each column.
217
218 column_value_pairs
219 Returns a hash (in list context) or reference to a hash (in scalar
220 context) of column name and value pairs. The keys of the hash are the
221 names of the columns. The values are retrieved by calling the accessor
222 method for each column.
223
224 dirty_columns [ NAMES | COLUMNS ]
225 Given a list of column names or
226 Rose::DB::Object::Metadata::Column-derived objects, mark each column in
227 the invoking object as modifed.
228
229 If passed no arguments, returns a list of all modified columns in list
230 context or the number of modified columns in scalar context.
231
232 forget_related [ NAME | PARAMS ]
233 Given a foreign key or relationship name, forget any previously loaded
234 objects related by the specified foreign key or relationship.
235 Normally, any objects loaded by the default accessor methods for
236 relationships and foreign keys are fetched from the database only the
237 first time they are asked for, and simply returned thereafter. Asking
238 them to be "forgotten" causes them to be fetched anew from the database
239 the next time they are asked for.
240
241 If the related object name is passed as a plain string NAME, then a
242 foreign key with that name is looked up. If no such foreign key
243 exists, then a relationship with that name is looked up. If no such
244 relationship or foreign key exists, a fatal error will occur. Example:
245
246 $foo->forget_related('bar');
247
248 It's generally not a good idea to add a foreign key and a relationship
249 with the same name, but it is technically possible. To specify the
250 domain of the name, pass the name as the value of a "foreign_key" or
251 "relationship" parameter. Example:
252
253 $foo->forget_related(foreign_key => 'bar');
254 $foo->forget_related(relationship => 'bar');
255
256 has_loaded_related [ NAME | PARAMS ]
257 Given a foreign key or relationship name, return true if one or more
258 related objects have been loaded into the current object, false
259 otherwise.
260
261 If the name is passed as a plain string NAME, then a foreign key with
262 that name is looked up. If no such foreign key exists, then a
263 relationship with that name is looked up. If no such relationship or
264 foreign key exists, a fatal error will occur. Example:
265
266 $foo->has_loaded_related('bar');
267
268 It's generally not a good idea to add a foreign key and a relationship
269 with the same name, but it is technically possible. To specify the
270 domain of the name, pass the name as the value of a "foreign_key" or
271 "relationship" parameter. Example:
272
273 $foo->has_loaded_related(foreign_key => 'bar');
274 $foo->has_loaded_related(relationship => 'bar');
275
276 init_with_column_value_pairs [ HASH | HASHREF ]
277 Initialize an object with a hash or reference to a hash of column/value
278 pairs. This differs from the inherited init method in that it accepts
279 column names rather than method names. A column name may not be the
280 same as its mutator method name if the column is aliased, for example.
281
282 $p = Person->new; # assume "type" column is aliased to "person_type"
283
284 # init() takes method/value pairs
285 $p->init(person_type => 'cool', age => 30);
286
287 # Helper takes a hashref of column/value pairs
288 $p->init_with_column_value_pairs({ type => 'cool', age => 30 });
289
290 # ...or a hash of column/value pairs
291 $p->init_with_column_value_pairs(type => 'cool', age => 30);
292
293 init_with_json JSON
294 Initialize the object with a JSON-formatted string. The JSON string
295 must be in the format returned by the as_json (or
296 column_values_as_json) method. Example:
297
298 $p1 = Person->new(name => 'John', age => 30);
299 $json = $p1->as_json;
300
301 $p2 = Person->new;
302 $p2->init_with_json($json);
303
304 print $p2->name; # John
305 print $p2->age; # 30
306
307 init_with_deflated_tree TREE
308 This is the same as the init_with_tree method, except that it expects
309 all the values to be simple scalars suitable for storage in the
310 database (e.g., a date string like "2005-12-31" instead of a DateTime
311 object). In other words, the TREE should be in the format generated by
312 the as_tree method called with the "deflate" parameter set to true.
313 Initializing objects in this way is slightly more efficient.
314
315 init_with_tree TREE
316 Initialize the object with a Perl data structure in the format returned
317 from the as_tree method. Example:
318
319 $p1 = Person->new(name => 'John', age => 30);
320 $tree = $p1->as_tree;
321
322 $p2 = Person->new;
323 $p2->init_with_tree($tree);
324
325 print $p2->name; # John
326 print $p2->age; # 30
327
328 init_with_yaml YAML
329 Initialize the object with a YAML-formatted string. The YAML string
330 must be in the format returned by the as_yaml (or
331 column_values_as_yaml) method. Example:
332
333 $p1 = Person->new(name => 'John', age => 30);
334 $yaml = $p1->as_yaml;
335
336 $p2 = Person->new;
337 $p2->init_with_yaml($yaml);
338
339 print $p2->name; # John
340 print $p2->age; # 30
341
342 insert_or_update [PARAMS]
343 If the object already exists in the database, then update it.
344 Otherwise, insert it. Any PARAMS are passed on to the call to save
345 (which is supplied with the appropriate "insert" or "update" boolean
346 parameter).
347
348 This method differs from the standard save method in that save decides
349 to insert or update based solely on whether or not the object was
350 previously loaded. This method will take the extra step of actually
351 attempting to load the object to see whether or not it's in the
352 database.
353
354 The return value of the save method is returned.
355
356 insert_or_update_on_duplicate_key [PARAMS]
357 Update or insert a row with a single SQL statement, depending on
358 whether or not a row with the same primary or unique key already
359 exists. Any PARAMS are passed on to the call to save (which is
360 supplied with the appropriate "insert" or "update" boolean parameter).
361
362 If the current database does not support the "ON DUPLICATE KEY UPDATE"
363 SQL extension, then this method simply calls the insert_or_update
364 method, passing all PARAMS.
365
366 Currently, the only database that supports "ON DUPLICATE KEY UPDATE" is
367 MySQL, and only in version 4.1.0 or later. You can read more about the
368 feature here:
369
370 <http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html>
371
372 Here's a quick example of the SQL syntax:
373
374 INSERT INTO table (a, b, c) VALUES (1, 2, 3)
375 ON DUPLICATE KEY UPDATE a = 1, b = 2, c = 3;
376
377 Note that there are two sets of columns and values in the statement.
378 This presents a choice: which columns to put in the "INSERT" part, and
379 which to put in the "UPDATE" part.
380
381 When using this method, if the object was previously loaded from the
382 database, then values for all columns are put in both the "INSERT" and
383 "UPDATE" portions of the statement.
384
385 Otherwise, all columns are included in both clauses except those
386 belonging to primary keys or unique keys which have only undefined
387 values. This is important because it allows objects to be updated
388 based on a single primary or unique key, even if other possible keys
389 exist, but do not have values set. For example, consider this table
390 with the following data:
391
392 CREATE TABLE parts
393 (
394 id INT PRIMARY KEY,
395 code CHAR(3) NOT NULL,
396 status CHAR(1),
397
398 UNIQUE(code)
399 );
400
401 INSERT INTO parts (id, code, status) VALUES (1, 'abc', 'x');
402
403 This code will update part id 1, setting its "status" column to "y".
404
405 $p = Part->new(code => 'abc', status => 'y');
406 $p->insert_or_update_on_duplicate_key;
407
408 The resulting SQL:
409
410 INSERT INTO parts (code, status) VALUES ('abc', 'y')
411 ON DUPLICATE KEY UPDATE code = 'abc', status = 'y';
412
413 Note that the "id" column is omitted because it has an undefined value.
414 The SQL statement will detect the duplicate value for the unique key
415 "code" and then run the "UPDATE" portion of the query, setting "status"
416 to "y".
417
418 This method returns true if the row was inserted or updated
419 successfully, false otherwise. The true value returned on success will
420 be the object itself. If the object overloads its boolean value such
421 that it is not true, then a true value will be returned instead of the
422 object itself.
423
424 Yes, this method name is very long. Remember that you can rename
425 methods on import. It is expected that most people will want to rename
426 this method to "insert_or_update", using it in place of the normal
427 insert_or_update helper method:
428
429 package My::DB::Object;
430 ...
431 use Rose::DB::Object::Helpers
432 { insert_or_update_on_duplicate_key => 'insert_or_update' };
433
434 load_or_insert [PARAMS]
435 Try to load the object, passing PARAMS to the call to the load()
436 method. The parameter "speculative => 1" is automatically added to
437 PARAMS. If no such object is found, then the object is inserted.
438
439 Example:
440
441 # Get object id 123 if it exists, otherwise create it now.
442 $obj = MyDBObject->new(id => 123)->load_or_insert;
443
444 load_or_save [PARAMS]
445 Try to load the object, passing PARAMS to the call to the load()
446 method. The parameter "speculative => 1" is automatically added to
447 PARAMS. If no such object is found, then the object is saved.
448
449 This methods differs from load_or_insert in that the save method will
450 also save sub-objects. See the documentation for Rose::DB::Object's
451 save method for more information.
452
453 Example:
454
455 @perms = (Permission->new(...), Permission->new(...));
456
457 # Get person id 123 if it exists, otherwise create it now
458 # along with permission sub-objects.
459 $person = Person->new(id => 123, perms => \@perms)->load_or_save;
460
461 load_speculative [PARAMS]
462 Try to load the object, passing PARAMS to the call to the load() method
463 along with the "speculative => 1" parameter. See the documentation for
464 Rose::DB::Object's load method for more information.
465
466 Example:
467
468 $obj = MyDBObject->new(id => 123);
469
470 if($obj->load_speculative)
471 {
472 print "Found object id 123\n";
473 }
474 else
475 {
476 print "Object id 123 not found\n";
477 }
478
479 new_from_json JSON
480 The method is the equivalent of creating a new object and then calling
481 the init_with_json method on it, passing JSON as an argument. See the
482 init_with_json method for more information.
483
484 new_from_deflated_tree TREE
485 The method is the equivalent of creating a new object and then calling
486 the init_with_deflated_tree method on it, passing TREE as an argument.
487 See the init_with_deflated_tree method for more information.
488
489 new_from_tree TREE
490 The method is the equivalent of creating a new object and then calling
491 the init_with_tree method on it, passing TREE as an argument. See the
492 init_with_tree method for more information.
493
494 new_from_yaml YAML
495 The method is the equivalent of creating a new object and then calling
496 the init_with_yaml method on it, passing YAML as an argument. See the
497 init_with_yaml method for more information.
498
499 strip [PARAMS]
500 This method prepares an object for serialization by stripping out
501 internal structures known to contain code references or other values
502 that do not survive serialization. The object itself is returned, now
503 stripped.
504
505 Note: Operations that were scheduled to happen "on save()" will also be
506 stripped out by this method. Examples include the databsae update or
507 insertion of any child objects attached to the parent object using
508 "get_set_on_save", "add_on_save", or "delete_on_save" methods. If such
509 operations exist, an exception will be thrown unless the
510 "strip_on_save_ok" parameter is true.
511
512 If your object has these kinds of pending changes, either save() first
513 and then strip(), or clone() and then strip() the clone.
514
515 By default, the db object and all sub-objects (foreign keys or
516 relationships) are removed. PARAMS are optional name/value pairs.
517 Valid PARAMS are:
518
519 leave [ NAME | ARRAYREF ]
520 This parameter specifies which items to leave un-stripped. The
521 value may be an item name or a reference to an array of item names.
522 Valid names are:
523
524 db Do not remove the db object. The db object will have its DBI
525 database handle (dbh) removed, however.
526
527 foreign_keys
528 Do not removed sub-objects that have already been loaded by
529 this object through foreign keys.
530
531 relationships
532 Do not removed sub-objects that have already been loaded by
533 this object through relationships.
534
535 related_objects
536 Do not remove any sub-objects (foreign keys or relationships)
537 that have already been loaded by this object. This option is
538 the same as specifying both the "foreign_keys" and
539 "relationships" names.
540
541 strip_on_save_ok BOOL
542 If true, do not throw an exception when pending "on-save" changes
543 exist in the object; just strip them. (See description above for
544 details.)
545
546 traverse_depth_first [ CODEREF | PARAMS ]
547 Do a depth-first traversal of the Rose::DB::Object-derived object that
548 this method is called on, descending into related objects. If a
549 reference to a subroutine is passed as the sole argument, it is taken
550 as the value of the "object" key to the "handlers" parameter hash (see
551 below). Otherwise, PARAMS name/value pairs are expected. Valid
552 parameters are:
553
554 allow_loops BOOL
555 If true, allow loops during the traversal (e.g., A -> B -> C -> A).
556 The default value is false.
557
558 context SCALAR
559 An arbitrary context variable to be passed along to (and possibly
560 modified by) each handler routine (see "handlers" parameter below).
561 The context may be any scalar value (e.g., an object, a reference
562 to a hash, etc.)
563
564 exclude CODEREF
565 A reference to a subroutine that is called on each
566 Rose::DB::Object-derived object encountered during the traversal.
567 It is passed the object, the parent object (undef, if none), and
568 the Rose::DB::Object::Metadata::Relationship-derived object
569 (undef, if none) that led to this object. If the subroutine
570 returns true, then this object is not processed. Example:
571
572 exclude => sub
573 {
574 my($object, $parent, $rel_meta) = @_;
575 ...
576 return 1 if($should_exclude);
577 return 0;
578 },
579
580 force_load BOOL
581 If true, related sub-objects will be loaded from the database. If
582 false, then only the sub-objects that have already been loaded from
583 the database will be traversed. The default is false.
584
585 handlers HASHREF
586 A reference to a hash of handler subroutines. Valid keys, calling
587 context, and the arguments passed to the referenced subroutines are
588 as follows.
589
590 object
591 This handler is called whenever a Rose::DB::Object-derived
592 object is encountered. This includes the object that
593 traverse_depth_first was called on as well as any sub-objects.
594 The handler is passed the object, the "context", the parent
595 object (undef, if none), the
596 Rose::DB::Object::Metadata::Relationship-derived object through
597 which this object was arrived at (undef if none), and the
598 depth.
599
600 The handler must return the value to be used as the "context"
601 during the traversal of any related sub-objects. The context
602 returned may be different than the context passed in. Example:
603
604 handlers =>
605 {
606 object => sub
607 {
608 my($object, $context, $parent, $rel_meta, $depth) = @_;
609 ...
610
611 return $context; # Important!
612 }
613 ...
614 }
615
616 relationship
617 This handler is called just before a
618 Rose::DB::Object::Metadata::Relationship-derived object is
619 descended into (i.e., just before the sub-objectes related
620 through this relationship are processed). The handler is passed
621 the object that contains the relationship, the "context", the
622 "context", and the relationship object itself.
623
624 The handler must return the value to be used as the "context"
625 during the traversal of the objects related through this
626 relationship. (If you do not define this handler, then the
627 current context object will be used.) The context returned may
628 be different than the context passed in. Example:
629
630 handlers =>
631 {
632 relationship => sub
633 {
634 my($object, $context, $rel_meta) = @_;
635 ...
636
637 return $context; # Important!
638 }
639 ...
640 }
641
642 loop_avoided
643 This handler is called after the traversal refuses to process a
644 sub-object in order to avoid a loop. (This only happens if the
645 "allow_loops" is parameter is false, obviously.) The handler
646 is passed the object that was not processed, the "context", the
647 parent object, the previous "context", and the
648 Rose::DB::Object::Metadata::Relationship-derived object through
649 which the sub-object was related. Example:
650
651 handlers =>
652 {
653 loop_avoided => sub
654 {
655 my($object, $context, $parent, $prev_context, $rel_meta) = @_;
656 ...
657 }
658 ...
659 }
660
661 max_depth DEPTH
662 Do not descend past DEPTH levels. Depth is an integer starting
663 from 0 for the object that the traverse_depth_first method was
664 called on and increasing with each level of related objects. The
665 default value is 100.
666
667 prune CODEREF
668 A reference to a subroutine that is called on each
669 Rose::DB::Object::Metadata::Relationship-derived object encountered
670 during traversal. It is passed the relationship object, the parent
671 object, and the depth. If the subroutine returns true, then the
672 entire sub-tree below this relationship will not be traversed.
673 Example:
674
675 prune => sub
676 {
677 my($rel_meta, $object, $depth) = @_;
678 ...
679 return 1 if($should_prune);
680 return 0;
681 },
682
684 John C. Siracusa (siracusa@gmail.com)
685
687 Copyright (c) 2010 by John C. Siracusa. All rights reserved. This
688 program is free software; you can redistribute it and/or modify it
689 under the same terms as Perl itself.
690
691
692
693perl v5.32.1 2021-01-27 Rose::DB::Object::Helpers(3)