1Rose::DB::Object::ConveUnsteironCMoanntargiebru(t3e)d PeRrolseD:o:cDuBm:e:nOtbajteicotn::ConventionManager(3)
2
3
4

NAME

6       Rose::DB::Object::ConventionManager - Provide missing metadata by
7       convention.
8

SYNOPSIS

10         package My::Product;
11
12         use base 'Rose::DB::Object';
13
14         __PACKAGE__->meta->setup(columns => [ ... ]);
15
16         # No table is set above, but look at this: the
17         # convention manager provided one for us.
18         print __PACKAGE__->meta->table; # "products"
19
20         ##
21         ## See the EXAMPLE section below for a more complete demonstration.
22         ##
23

DESCRIPTION

25       Each Rose::DB::Object-derived object has a convention manager that it
26       uses to fill in missing metadata.  The convention manager encapsulates
27       a set of rules (conventions) for generating various pieces of metadata
28       in the absence of explicitly specified values: table names, column
29       names, etc.
30
31       Each Rose::DB::Object-derived class's convention manager object is
32       stored in the convention_manager attribute of its
33       Rose::DB::Object::Metadata (meta) object.
34       Rose::DB::Object::ConventionManager is the default convention manager
35       class.
36
37       The object method documentation below describes both the purpose of
38       each convention manager method and the particular rules that
39       Rose::DB::Object::ConventionManager follows to fulfill that purpose.
40       Subclasses must honor the purpose of each method, but are free to use
41       any rules they choose.
42
43       Note well: When reading the descriptions of the rules used by each
44       convention manager method below, remember that only values that are
45       missing will be set by the convention manager.  Explicitly providing a
46       value for a piece of metadata obviates the need for the convention
47       manager to generate one.
48
49       If insufficient information is available, or if the convention manager
50       simply declines to fulfill a request, undef may be returned from any
51       metadata-generating method.
52
53       In the documentation, the adjectives "local" and "foreign" are used to
54       distinguish between the things that belong to the convention manager's
55       class and the class on "the other side" of the inter-table
56       relationship, respectively.
57

SUMMARY OF DEFAULT CONVENTIONS

59       Although the object method documentation below includes all the
60       information required to understand the default conventions, it's also
61       quite spread out.  What follows is a summary of the default
62       conventions.  Some details have necessarily been omitted or simplified
63       for the sake of brevity, but this summary should give you a good
64       starting point for further exploration.
65
66       Here's a brief summary of the default conventions as implemented in
67       Rose::DB::Object::ConventionManager.
68
69       Table, column, foreign key, and relationship names are lowercase, with
70       underscores separating words.
71           Examples:  "products", "street_address", "date_created",
72           "vendor_id".
73
74       Table names are plural.
75           Examples: "products", "vendors", "codes", "customer_details",
76           "employee_addresses".
77
78           (This convention can be overridden via the tables_are_singular
79           method.)
80
81       Class names are singular, title-cased, with nothing separating words.
82           Examples: "Product", "Vendor", "Code", "CustomerDetail",
83           "EmployeeAddress".
84
85       Primary key column names do not contain the table name.
86           For example, the primary key column name in the "products" table
87           might be "id" or "sku", but should not be "product_id" or
88           "product_sku".
89
90       Foreign key column names are made from the singular version of the
91       foreign table's name joined (with an underscore) to the foreign table's
92       key column name.
93           Examples: "product_sku", "vendor_id", "employee_address_id".
94
95       One-to-one and many-to-one relationship names are singular.
96           Examples: "product", "vendor", "code".  These relationships may
97           point to zero or one foreign object.  The default method names
98           generated from such relationships are based on the relationship
99           names, so singular names make the most sense.
100
101       One-to-many and many-to-many relationship names are plural.
102           Examples: "colors", "prices", "customer_details".  These
103           relationships may point to more than one foreign object.  The
104           default method names generated from such relationships are based on
105           the relationship names, so plural names make the most sense.
106
107       Mapping tables and their associated classes that participate in many-
108       to-many relationships are named according a formula that combines the
109       names of the two classes/tables that are being linked.
110           See the auto_relationship, looks_like_map_class, and
111           looks_like_map_table documentation for all the details.
112

CONSTRUCTOR

114       new PARAMS
115           Constructs a new object based on PARAMS, where PARAMS are
116           name/value pairs.  Any object attribute is a valid parameter name.
117

OBJECT METHODS

119       auto_column_method_name TYPE, COLUMN, NAME, OBJECT_CLASS
120           Given a Rose::DB::Object::Metadata::Column column type, a
121           Rose::DB::Object::Metadata::Column object or column name, a default
122           method name, and a Rose::DB::Object-derived class name, return an
123           appropriate method name.  The default implementation simply returns
124           undef, relying on the hard-coded default method-type-to-name
125           mapping implemented in Rose::DB::Object::Metadata's
126           method_name_from_column method.
127
128       auto_foreign_key NAME [, SPEC]
129           Given a foreign key name and an optional reference to a hash SPEC
130           of the type passed to Rose::DB::Object::Metadata's add_foreign_keys
131           method, return an appropriately constructed
132           Rose::DB::Object::Metadata::ForeignKey object.
133
134           The foreign key's class name is generated by calling
135           related_table_to_class, passing NAME and the convention manager's
136           class as arguments.  An attempt is made is load the class.  If this
137           fails, the foreign key's class name is not set.
138
139           The foreign key's key_columns are only set if both the "local" and
140           "foreign" tables have single-column primary keys.  The foreign
141           class's primary key column name is used as the foreign column in
142           the  key_columns map.  If there is a local column with the same
143           name as the foreign key name, and if that column is aliased (making
144           way for the foreign key method to use that name), then that is used
145           as the local column.  If not, then the local column name is
146           generated by joining the foreign key name and the foreign class's
147           primary key column name with an underscore.  If no column by that
148           name exists, then the search is abandoned.  Example:
149
150           Given these pieces:
151
152               Name        Description                        Value
153               ---------   --------------------------------   -------
154               NAME        Foreign key name                   vendor
155               FCLASS      Foreign class                      My::Vendor
156               FPK         Foreign primary key column name    id
157
158           Consider column maps in this order:
159
160               Value                   Formula
161               ---------------------   ----------------------
162               { vendor => 'id' }      { NAME => FPK }
163               { vendor_id => 'id' }   { <NAME>_<FPK> => FPK }
164
165       auto_foreign_key_name FOREIGN_CLASS, CURRENT_NAME, KEY_COLUMNS,
166       USED_NAMES
167           Given the name of a foreign class, the current foreign key name (if
168           any), a reference to a hash of key columns, and a reference to a
169           hash whose keys are foreign key names already used in this class,
170           return a name for the foreign key.
171
172           If there is more than one pair of columns in KEY_COLUMNS, then the
173           name is generated by calling plural_to_singular, passing the table
174           name of the foreign class.  The CURRENT_NAME is used if the call to
175           plural_to_singular does not return a true value.
176
177           If there is just one pair of columns in KEY_COLUMNS, and if the
178           name of the local column ends with an underscore and the name of
179           the referenced column, then that part of the column name is removed
180           and the remaining string is used as the foreign key name.  For
181           example, given the following tables:
182
183               CREATE TABLE categories
184               (
185                 id  SERIAL PRIMARY KEY,
186                 ...
187               );
188
189               CREATE TABLE products
190               (
191                 category_id  INT REFERENCES categories (id),
192                 ...
193               );
194
195           The foreign key name would be "category", which is the name of the
196           referring column ("category_id") with an underscore and the name of
197           the referenced column ("_id") removed from the end of it.
198
199           If the foreign key has only one column, but it does not meet the
200           criteria described above, then the name is generated by calling
201           plural_to_singular, passing the table name of the foreign class.
202           The CURRENT_NAME is used if the call to plural_to_singular does not
203           return a true value.
204
205           If the name selected using the above techniques is in the
206           USED_NAMES hash, or is the same as that of an existing or potential
207           method in the target class, then the suffixes "_obj" and "_object"
208           are tried in that order.  If neither of those suffixes resolves the
209           situation, then ascending numeric suffixes starting with "1" are
210           tried until a unique name is found.
211
212       auto_manager_base_name TABLE, CLASS
213           Given a table name and the name of the Rose::DB::Object-derived
214           class that fronts it, return a base name suitable for use as the
215           value of the "base_name" parameter to Rose::DB::Object::Manager's
216           make_manager_methods method.
217
218           If no table is specified then the table name is derived from the
219           current class name by calling class_to_table_plural.
220
221           If tables_are_singular is true, then TABLE is passed to the
222           singular_to_plural method and the result is returned.  Otherwise,
223           TABLE is returned as-is.
224
225       auto_manager_base_class
226           Return the class that all manager classes will default to
227           inheriting from.  By default this will be
228           Rose::DB::Object::Manager.
229
230       auto_manager_class_name CLASS
231           Given the name of a Rose::DB::Object-derived class, returns a class
232           name for a Rose::DB::Object::Manager-derived class to manage such
233           objects.  The default implementation simply appends "::Manager" to
234           the Rose::DB::Object-derived class name.
235
236       auto_manager_method_name TYPE, BASE_NAME, OBJECT_CLASS
237           Given the specified Rose::DB::Object::Manager method type, base
238           name, and object class return an appropriate manager method name.
239           The default implementation simply returns undef, relying on the
240           hard-coded default method-type-to-name mapping implemented in
241           Rose::DB::Object::Manager's  make_manager_methods method.
242
243       auto_relationship_name_many_to_many FK, MAPCLASS
244           Return the name of a "many to many" relationship that fetches
245           objects from the table pointed to by the
246           Rose::DB::Object::Metadata::ForeignKey object FK by going through
247           the class MAPCLASS.
248
249           The default implementation passes the name of the table pointed to
250           by FK through the singular_to_plural method in order to build the
251           name.
252
253           If the selected name is the name of an existing or potential method
254           in the target class, then the suffixes "_objs" and "_objects" are
255           tried in that order.  If neither of those suffixes resolves the
256           situation, then ascending numeric suffixes starting with "1" are
257           tried until a unique name is found.
258
259       auto_relationship_name_one_to_many TABLE, CLASS
260           Return the name of a "one to many" relationship that fetches
261           objects from the specified TABLE and CLASS.
262
263           If tables_are_singular is true, then TABLE is passed to the
264           singular_to_plural method and the result is used as the name.
265           Otherwise, TABLE is used as-is.
266
267           If the selected name is the name of an existing or potential method
268           in the target class, then the suffixes "_objs" and "_objects" are
269           tried in that order.  If neither of those suffixes resolves the
270           situation, then ascending numeric suffixes starting with "1" are
271           tried until a unique name is found.
272
273       auto_relationship_name_one_to_one TABLE, CLASS
274           Return the name of a "one to one" relationship that fetches an
275           object from the specified TABLE and CLASS.  The default
276           implementation returns a singular version of the table name.
277
278           If the selected name is the name of an existing or potential method
279           in the target class, then the suffixes "obj_" and "_object" are
280           tried in that order.  If neither of those suffixes resolves the
281           situation, then ascending numeric suffixes starting with "1" are
282           tried until a unique name is found.
283
284       auto_primary_key_column_names
285           Returns a reference to an array of primary key column names.
286
287           If a column named "id" exists, it is selected as the sole primary
288           key column name.  If not, the column name generated by joining the
289           return value of class_to_table_singular with "_id" is considered.
290           If no column with that name exists, then the first column (sorted
291           alphabetically) whose type is "serial" is selected.  If all of the
292           above fails, then the first column is selected as the primary key
293           column (assuming one exists).
294
295           Examples:
296
297               My::A->meta->columns(qw(a a_id id));
298               print My::A->meta->primary_key_columns; # "id"
299
300               My::B->meta->columns(qw(b b_id foo));
301               print My::B->meta->primary_key_columns; # "a_id"
302
303               My::D->meta->columns
304               (
305                 cnt  => { type => 'int' },
306                 dub  => { type => 'serial' },
307                 foo  => { type => 'serial'},
308                 a_id => { type => 'int' }
309               )
310
311               print My::D->meta->primary_key_columns; # "dub"
312
313               My::C->meta->columns(qw(foo bar baz));
314               print My::C->meta->primary_key_columns; # "foo"
315
316       auto_relationship NAME, RELATIONSHIP_CLASS [, SPEC]
317           Given a relationship name, a
318           Rose::DB::Object::Metadata::Relationship-derived class name, and an
319           optional reference to a hash SPEC of the type passed to
320           Rose::DB::Object::Metadata's add_relationships method, return an
321           appropriately constructed
322           Rose::DB::Object::Metadata::Relationship-derived object.
323
324           If the relationship's type is "one to one" or "many to one", then
325           the relationship's class name is generated by calling
326           related_table_to_class, passing NAME and the convention manager's
327           class as arguments.  An attempt is made is load the class.  If this
328           fails, the relationship's class name is not set.
329
330           The column map for "one to one" and "many to one" relationships is
331           generated using the same rules used to generate key_columns in the
332           auto_foreign_key method.
333
334           If the relationship's type is "one to many" then the relationship's
335           class name is generated by calling plural_to_singular on NAME, then
336           passing that value along with the convention manager's class to the
337           related_table_to_class method.  An attempt is made is load the
338           class.  If this fails, the relationship's class name is not set.
339
340           The column map for a "one to many" relationship is only set if both
341           the "local" and "foreign" tables have single-column primary keys.
342           The following ordered list of combinations is considered.
343
344           Given:
345
346              Local class:   My::Product
347              Foreign class: My::Price
348              Relationship:  prices
349
350           Generate these pieces:
351
352               Name        Description                         Value
353               ---------   ---------------------------------   -------
354               LTABLE_S    Local class_to_table_singular()     product
355               LPK         Local primary key column name       id
356               FPK         Foreign primary key column name     id
357
358           Consider column maps in this order:
359
360               Value                     Formula
361               ----------------------    --------------------------
362               { id => 'product' }       { LPK => LTABLE_S }
363               { id => 'product_id' }    { LPK => <LTABLE_S>_<PK> }
364
365           The first value whose foreign column actually exists in the foreign
366           table is chosen.
367
368           If the relationship's type is "many to many" then the
369           relationship's map_class is chosen from a list of possibilities.
370           This list is generated by constructing singular and plural versions
371           of the local and foreign class names (sans prefixes) and then
372           joining them in various ways, all re-prefixed by the class prefix
373           of the convention manager's class.  Example:
374
375           Given:
376
377              Local class:   My::Product
378              Foreign class: My::Color
379              Relationship:  colors
380
381           Generate these pieces:
382
383               Name        Description                         Value
384               ---------   ---------------------------------   -------
385               PREFIX      Local class prefix                  My::
386               LCLASS_S    Unprefixed local class, singular    Product
387               LCLASS_P    Unprefixed local class, plural      Products
388               FCLASS_S    Unprefixed foreign class, singular  Color
389               FCLASS_P    Unprefixed foreign class, plural    Colors
390
391           Consider map class names in this order:
392
393               Value                   Formula
394               ---------------         ---------------------
395               My::ProductsColorsMap   <PREFIX><LCLASS_P><FCLASS_P>Map
396               My::ProductColorMap     <PREFIX><LCLASS_S><FCLASS_S>Map
397               My::ColorsProductsMap   <PREFIX><FCLASS_P><LCLASS_P>Map
398               My::ColorProductMap     <PREFIX><FCLASS_S><LCLASS_S>Map
399               My::ProductsColors      <PREFIX><LCLASS_P><FCLASS_P>
400               My::ProductColors       <PREFIX><LCLASS_S><FCLASS_P>
401               My::ColorsProducts      <PREFIX><FCLASS_P><LCLASS_P>
402               My::ColorProducts       <PREFIX><FCLASS_S><LCLASS_P>
403               My::ColorMap            <PREFIX><FCLASS_S>Map
404               My::ColorsMap           <PREFIX><FCLASS_P>Map
405               My::ProductMap          <PREFIX><LCLASS_S>Map
406               My::ProductsMap         <PREFIX><LCLASS_P>Map
407
408           The first class found that inherits from Rose::DB::Object and is
409           loaded successfully will be chosen as the relationship's map_class.
410
411       auto_table_name
412           Returns a table name for the convention manager's class.
413
414           Class names are singular and table names are plural.  To build the
415           table name, the class prefix is removed from the class name,
416           transitions from lowercase letters or digits to uppercase letters
417           have underscores inserted, and the whole thing is converted to
418           lowercase.
419
420           Examples:
421
422               Class         Table
423               -----------   --------
424               Product       products
425               My::Product   products
426               My::BigBox    big_boxes
427               My5HatPig     my5_hat_pig
428
429       class [CLASS]
430           Get or set the Rose::DB::Object-derived class that this convention
431           manager belongs to.
432
433       class_prefix CLASS
434           Given a class name, return the prefix, if any, before the last
435           component of the namespace, including the final "::".  If there is
436           no prefix, an empty string is returned.
437
438           Examples:
439
440               Class         Prefix
441               -----------   --------------
442               Product       <empty string>
443               My::Product   My::
444               A::B::C::D    A::B::C::
445
446       class_to_table_plural [CLASS]
447           Given a class name, or the convention manager's class if omitted,
448           return a plural version of the corresponding table name.
449
450           To do this, the output of the class_to_table_singular method is
451           passed to a call to the singular_to_plural method.  (The CLASS
452           argument, if any, is passed to the call to
453           class_to_table_singular.)
454
455           Examples:
456
457               Class         Table
458               -----------   --------
459               Product       products
460               My::Product   products
461               My::Box       boxes
462
463       class_to_table_singular [CLASS]
464           Given a class name, or the convention manager's class if omitted,
465           return a singular version of the corresponding table name.
466
467           Examples:
468
469               Class         Table
470               -----------   --------
471               Product       product
472               My::Product   product
473               My::Box       box
474
475       force_lowercase [BOOL]
476           Get or set a boolean value that indicates whether or not metadata
477           entity names should be forced to lowercase even when the related
478           entity is uppercase or mixed case.  ("Metadata entities" are thing
479           like columns, relationships, and foreign keys.)  The default value
480           is false.
481
482       is_map_class CLASS
483           Returns true if CLASS is a map class used as part of a many to many
484           relationship, false if it does not.
485
486           The default implementations returns true if CLASS is derived from
487           Rose::DB::Object and its table name looks like a map table name
488           according to the looks_like_map_table method and the
489           looks_like_map_class method returns either true or undef.
490
491           Override this method to control which classes are considered map
492           classes.  Note that it may be called several times on the same
493           class at various stages of that class's construction.
494
495       looks_like_map_class CLASS
496           Given the class name CLASS, returns true if it looks like the name
497           of a map class used as part of a many to many relationship, false
498           (but defined) if it does not, and undef if it's unsure.
499
500           The default implementation returns true if CLASS is derived from
501           Rose::DB::Object and has exactly two foreign keys.  It returns
502           false (but defined) if CLASS is derived from Rose::DB::Object and
503           has been initialized (or if the foreign keys have been auto-
504           initialized) and the CLASS has no deferred foreign keys.  It
505           returns undef otherwise.
506
507       looks_like_map_table TABLE
508           Returns true if TABLE looks like the name of a mapping table used
509           as part of a many to many relationship, false (but defined) if it
510           does not, and undef if it's unsure.
511
512           The default implementation returns true if TABLE is in one of these
513           forms:
514
515               Regex                     Examples
516               -----------------------   -----------------------------
517               (\w+_){2,}map             pig_toe_map, pig_skin_toe_map
518               (\w+_)*\w+_(\w+_)*\w+s    pig_toes, pig_skin_toe_jams
519               (\w+_)*\w+s_(\w+_)*\w+s   pigs_toes, pig_skins_toe_jams
520
521           It returns false otherwise.
522
523       meta [META]
524           Get or set the Rose::DB::Object::Metadata object associated with
525           the class that this convention manager belongs to.
526
527       plural_to_singular STRING
528           Returns the singular version of STRING.  If a
529           plural_to_singular_function is defined, then this method simply
530           passes STRING to that function.
531
532           Otherwise, the following rules are applied, case-insensitively.
533
534           * If STRING ends in "ies", then the "ies" is replaced with "y".
535
536           * If STRING ends in "ses" then the "ses" is replaced with "s".
537
538           * If STRING matches "/[aeiouy]ss$/i", it is returned unmodified.
539
540           For all other cases, the letter "s" is removed from the end of
541           STRING and the result is returned.
542
543       plural_to_singular_function [CODEREF]
544           Get or set a reference to the function used to convert strings to
545           singular.  The function should take a single string as an argument
546           and return a singular version of the string.  This function is
547           undefined by default.
548
549       related_table_to_class TABLE, LOCAL_CLASS
550           Given a table name and a local class name, return the name of the
551           related class that fronts the table.
552
553           To do this, table_to_class is called with TABLE and the
554           class_prefix of LOCAL_CLASS passed as arguments.
555
556           Examples:
557
558               Table         Local Class     Related Class
559               -----------   ------------    ----------------
560               prices        My::Product     My::Price
561               big_hats      A::B::FooBar    A::B::BigHat
562               a1_steaks     Meat            A1Steak
563
564       singular_to_plural STRING
565           Returns the plural version of STRING.  If a
566           singular_to_plural_function is defined, then this method simply
567           passes STRING to that function.  Otherwise, the following rules are
568           applied, case-insensitively, to form the plural.
569
570           * If STRING ends in "x", "ss", or "es", then "es" is appended.
571
572           * If STRING ends in "y" then the "y" is replaced with "ies".
573
574           * If STRING ends in "s" then it is returned as-is.
575
576           * Otherwise, "s" is appended.
577
578       singular_to_plural_function [CODEREF]
579           Get or set a reference to the function used to convert strings to
580           plural.  The function should take a single string as an argument
581           and return a plural version of the string.  This function is
582           undefined by default.
583
584       table_singular
585           Let TABLE be the return value of the table method called on the
586           meta attribute of this object.
587
588           If tables_are_singular is true, then TABLE is returned as-is.
589           Otherwise, TABLE is passed to the plural_to_singular method and the
590           result is returned.  Otherwise, TABLE is returned as-is.
591
592       table_plural
593           Let TABLE be the return value of the table method called on the
594           meta attribute of this object.
595
596           If tables_are_singular is true, then TABLE is passed to the
597           singular_to_plural method and the result is returned.  Otherwise,
598           TABLE is returned as-is.
599
600       table_to_class TABLE [, PREFIX]
601           Given a table name and an optional class prefix, return the
602           corresponding class name.  The prefix will be appended to the class
603           name, if present.  The prefix should end in "::".
604
605           To do this, any letter that follows an underscore ("_") in the
606           table name is replaced with an uppercase version of itself, and the
607           underscore is removed.
608
609           Examples:
610
611               Table         Prefix   Class
612               -----------   ------   -----------
613               products      My::     My::Product
614               products      <none>   Product
615               big_hats      My::     My::BigHat
616               my5_hat_pig   <none>   My5HatPig
617
618       tables_are_singular [BOOL]
619           Get or set a boolean value that indicates whether or not table
620           names are expected to be singular.  The default value is false,
621           meaning that table names are expected to be plural.
622

PROTECTED API

624       These methods are not part of the public interface, but are supported
625       for use by subclasses.  Put another way, given an unknown object that
626       "isa" Rose::DB::Object::Metadata::ConventionManager, there should be no
627       expectation that the following methods exist.  But subclasses, which
628       know the exact class from which they inherit, are free to use these
629       methods in order to implement the public API described above.
630
631       init_plural_to_singular_function
632           Override this method and return a reference to a function that
633           takes a single string as an argument and returns a singular version
634           of that string.
635
636       init_singular_to_plural_function
637           Override this method and return a reference to a function that
638           takes a single string as an argument and returns a plural version
639           of that string.
640

TIPS AND TRICKS

642       Much of the richness of a convention manager relies upon the quality of
643       the singular_to_plural and plural_to_singular methods.  The default
644       implementations are primitive at best.  For example,
645       singular_to_plural will not correctly form the plural of the word
646       "alumnus".
647
648       One easy way to improve this is by setting a custom
649       singular_to_plural_function.  Here's an example using the handy
650       Lingua::EN::Inflect module:
651
652           package My::Product;
653           ...
654           use Lingua::EN::Inflect;
655           $cm = __PACKAGE__->meta->convention_manager;
656
657           $cm->singular_to_plural_function(\&Lingua::EN::Inflect::PL);
658
659           print $cm->singular_to_plural('person'); # "people"
660
661       But that's a bit of a pain to do in every single class.  An easier way
662       to do it for all of your classes is to make a new
663       Rose::DB::Object::Metadata subclass that overrides the
664       init_convention_manager method, then make a Rose::DB::Object-derived
665       base class that uses your new metadata class.  Example:
666
667           package My::DB::Metadata;
668
669           use Rose::DB::Object::Metadata;
670           our @ISA = qw(Rose::DB::Object::Metadata);
671
672           use Lingua::EN::Inflect;
673
674           sub init_convention_manager
675           {
676             my $self = shift;
677
678             # Let the base class make ths convention manager object
679             my $cm = $self->SUPER::init_convention_manager(@_);
680
681             # Set the new singular-to-plural function
682             $cm->singular_to_plural_function(\&Lingua::EN::Inflect::PL);
683
684             # Return the modified convention manager
685             return $cm;
686           }
687
688           ...
689
690           package My::DB::Object;
691
692           use My::DB::Metadata;
693
694           use Rose::DB::Object;
695           our @ISA = qw(Rose::DB::Object);
696
697           sub meta_class { 'My::DB::Metadata' }
698
699           ...
700
701           package My::Person;
702
703           use My::DB::Object;
704           our @ISA = qw(My::DB::Object);
705
706           # The big pay-off: smart plurals!
707           print __PACKAGE__->meta->table; # "people"
708
709       You might wonder why I don't use Lingua::EN::Inflect in
710       Rose::DB::Object::ConventionManager to save you this effort.  The
711       answer is that the Lingua::EN::Inflect module adds almost a megabyte of
712       memory overhead on my system.  I'd rather not incur that overhead just
713       for the sake of being more clever about naming conventions.
714       Furthermore, as primitive as the default plural-forming is, at least
715       it's deterministic.  Guessing what Lingua::EN::Inflect will return is
716       not always easy, and the results can change depending on which version
717       Lingua::EN::Inflect you have installed.
718

EXAMPLE

720       Here's a complete example of nearly all of the major features of
721       Rose::DB::Object::ConventionManager.  Let's start with the database
722       schema.  (This example uses PostgreSQL, but any supported database with
723       native foreign key support will work.)
724
725         CREATE TABLE vendors
726         (
727           id    SERIAL NOT NULL PRIMARY KEY,
728           name  VARCHAR(255)
729         );
730
731         CREATE TABLE colors
732         (
733           code  CHAR(3) NOT NULL PRIMARY KEY,
734           name  VARCHAR(255)
735         );
736
737         CREATE TABLE products
738         (
739           id        SERIAL NOT NULL PRIMARY KEY,
740           name      VARCHAR(255),
741           vendor_id INT NOT NULL REFERENCES vendors (id)
742         );
743
744         CREATE TABLE prices
745         (
746           price_id    SERIAL NOT NULL PRIMARY KEY,
747           product_id  INT NOT NULL REFERENCES products (id),
748           region      CHAR(2) NOT NULL DEFAULT 'US',
749           price       DECIMAL(10,2) NOT NULL
750         );
751
752         CREATE TABLE product_colors
753         (
754           id           SERIAL NOT NULL PRIMARY KEY,
755           product_id   INT NOT NULL REFERENCES products (id),
756           color_code   CHAR(3) NOT NULL REFERENCES colors (code)
757         );
758
759       Now the classes:
760
761         # Rose::DB subclass to handle the db connection
762         package My::DB;
763
764         use base 'Rose::DB';
765
766         My::DB->register_db
767         (
768           type     => 'default',
769           domain   => 'default',
770           driver   => 'Pg',
771           database => 'test',
772           username => 'postgres',
773         );
774
775         ...
776
777         # Common Rose::DB::Object-derived base class for the other objects
778         package My::Object;
779
780         use My::DB;
781
782         use base 'Rose::DB::Object';
783
784         sub init_db { My::DB->new }
785
786         ...
787
788         package My::Price;
789
790         use base 'My::Object';
791
792         __PACKAGE__->meta->setup
793         (
794           columns =>
795           [
796             price_id   => { type => 'serial', not_null => 1 },
797             product_id => { type => 'int' },
798             region     => { type => 'char', length => 2, default => 'US' },
799             price      => { type => 'decimal', precision => 10, scale => 2 },
800           ],
801
802           foreign_keys => [ 'product' ],
803         );
804
805         ...
806
807         package My::Vendor;
808
809         use base 'My::Object';
810
811         __PACKAGE__->meta->setup
812         (
813           columns =>
814           [
815             id    => { type => 'serial', not_null => 1 },
816             name  => { type => 'varchar', length => 255 },
817           ],
818         );
819
820         ...
821
822         package My::Color;
823
824         use base 'My::Object';
825
826         __PACKAGE__->meta->setup
827         (
828           columns =>
829           [
830             code => { type => 'char', length => 3, not_null => 1 },
831             name => { type => 'varchar', length => 255 },
832           ],
833         );
834
835         ...
836
837         package My::Product;
838
839         use base 'My::Object';
840
841         __PACKAGE__->meta->setup
842         (
843           columns =>
844           [
845             id        => { type => 'serial', not_null => 1 },
846             name      => { type => 'varchar', length => 255 },
847             vendor_id => { type => 'int' },
848           ],
849
850           foreign_keys => [ 'vendor' ],
851
852           relationships =>
853           [
854             prices => { type => 'one to many' },
855             colors => { type => 'many to many' },
856           ],
857         );
858
859         ...
860
861         package My::ProductColors;
862
863         use base 'My::Object';
864
865         __PACKAGE__->meta->setup
866         (
867           columns      => [ qw(id product_id color_code) ],
868           foreign_keys => [ 'product', 'color' ],
869         );
870
871       Let's add some data:
872
873         INSERT INTO vendors (id, name) VALUES (1, 'V1');
874         INSERT INTO vendors (id, name) VALUES (2, 'V2');
875
876         INSERT INTO products (id, name, vendor_id) VALUES (1, 'A', 1);
877         INSERT INTO products (id, name, vendor_id) VALUES (2, 'B', 2);
878         INSERT INTO products (id, name, vendor_id) VALUES (3, 'C', 1);
879
880         INSERT INTO prices (product_id, region, price) VALUES (1, 'US', 1.23);
881         INSERT INTO prices (product_id, region, price) VALUES (1, 'DE', 4.56);
882         INSERT INTO prices (product_id, region, price) VALUES (2, 'US', 5.55);
883         INSERT INTO prices (product_id, region, price) VALUES (3, 'US', 5.78);
884         INSERT INTO prices (product_id, region, price) VALUES (3, 'US', 9.99);
885
886         INSERT INTO colors (code, name) VALUES ('CC1', 'red');
887         INSERT INTO colors (code, name) VALUES ('CC2', 'green');
888         INSERT INTO colors (code, name) VALUES ('CC3', 'blue');
889         INSERT INTO colors (code, name) VALUES ('CC4', 'pink');
890
891         INSERT INTO product_colors (product_id, color_code) VALUES (1, 'CC1');
892         INSERT INTO product_colors (product_id, color_code) VALUES (1, 'CC2');
893
894         INSERT INTO product_colors (product_id, color_code) VALUES (2, 'CC4');
895
896         INSERT INTO product_colors (product_id, color_code) VALUES (3, 'CC2');
897         INSERT INTO product_colors (product_id, color_code) VALUES (3, 'CC3');
898
899       (Be aware that not all databases are smart enough to track explicitly
900       setting serial column values as shown in the INSERT statements above.
901       Subsequent auto-generated serial values may conflict with the
902       explicitly set serial column values already in the table.  Values are
903       set explicitly here to make the examples easier to follow.  In "real"
904       code, you should let the serial columns populate automatically.)
905
906       Finally, the classes in action:
907
908         $p = My::Product->new(id => 1)->load;
909
910         print $p->vendor->name, "\n"; # "V1"
911
912         # "US: 1.23, DE: 4.56"
913         print join(', ', map { $_->region .': '. $_->price } $p->prices), "\n";
914
915         # "red, green"
916         print join(', ', map { $_->name } $p->colors), "\n";
917

AUTO-INIT EXAMPLE

919       Using Rose::DB::Object's auto-initialization feature, the Perl code can
920       be reduced to an  absurd degree.  Given the same database schema and
921       data shown in the example above, consider the following classes:
922
923         package My::Auto::Color;
924         use base 'My::Object';
925         __PACKAGE__->meta->auto_initialize;
926         ...
927
928         package My::Auto::Price;
929         use base 'My::Object';
930         __PACKAGE__->meta->auto_initialize;
931         ...
932
933         package My::Auto::ProductColors;
934         use base 'My::Object';
935         __PACKAGE__->meta->auto_initialize;
936         ...
937
938         package My::Auto::Vendor;
939         use base 'My::Object';
940         __PACKAGE__->meta->auto_initialize;
941         ...
942
943         package My::Auto::Product;
944         use base 'My::Object';
945         __PACKAGE__->meta->auto_initialize;
946
947       Not a single table, column, foreign key, or relationship is specified,
948       yet everything still works:
949
950         $p = My::Auto::Product->new(id => 1)->load;
951
952         print $p->vendor->name, "\n"; # "V1"
953
954         # "US: 1.23, DE: 4.56"
955         print join(', ', map { $_->region .': '. $_->price } $p->prices), "\n";
956
957         # "red, green"
958         print join(', ', map { $_->name } $p->colors), "\n";
959
960       More precisely, everything still works provided that you load all the
961       of the related modules.  For example, if you load "My::Auto::Product"
962       but don't load "My::Auto::Price" (either from within the
963       "My::Auto::Product" class or in your program itself), then the
964       "My::Auto::Product" will not have a prices() method (since your program
965       will have no knowledge of the "My::Auto::Price" class).  Use the loader
966       if you want to set up a bunch of related classes automatically without
967       worrying about this kind of thing.
968
969       Anyway, I don't recommend this kind of extreme approach, but it is an
970       effective demonstration of the power of the convention manager.
971

AUTHOR

973       John C. Siracusa (siracusa@gmail.com)
974

LICENSE

976       Copyright (c) 2010 by John C. Siracusa.  All rights reserved.  This
977       program is free software; you can redistribute it and/or modify it
978       under the same terms as Perl itself.
979
980
981
982perl v5.36.0                      2023-01R-o2s0e::DB::Object::ConventionManager(3)
Impressum