.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mixin::ExtraFields 3pm" .TH Mixin::ExtraFields 3pm "2023-01-07" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mixin::ExtraFields \- add extra stashes of data to your objects .SH "VERSION" .IX Header "VERSION" version 0.140003 .SH "SYNOPSIS" .IX Header "SYNOPSIS" If you use the ExtraFields mixin in your class: .PP .Vb 1 \& package Corporate::WorkOrder; \& \& use Mixin::ExtraFields \-fields => { \& id => \*(Aqworkorder_id\*(Aq, \& moniker => \*(Aqnote\*(Aq, \& driver => { HashGuts => { hash_key => \*(Aq_notes\*(Aq } } \& }; .Ve .PP \&...your objects will then have methods for manipulating their extra fields: .PP .Vb 1 \& my $workorder = Corporate::WorkOrder\->retrieve(1234); \& \& if ($workorder\->note_exists(\*(Aqdebug_next\*(Aq)) { \& warn $workorder\->note_get(\*(Aqdebug_next\*(Aq); \& $workorder\->note_delete(\*(Aqdebug_next\*(Aq); \& } \& \& if ($workorder\->note_get(\*(Aqtime_bomb\*(Aq)) { \& $workorder\->note_delete_all; \& $workorder\->note_set( \& last_explosion => time, \& explosion_cause => \*(Aqtime bomb\*(Aq, \& ); \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Sometimes your well-defined object needs a way to tack on arbirary extra fields. This might be a set of session-specific ephemeral data, a stash of settings that need to be easy to grow over time, or any sort of name-and-value parameters. Adding more and more methods can be cumbersome, and may not be helpful if the names vary greatly. Accessing an object's guts directly is simple, but is difficult to control when subclassing, and can make altering your object's structure difficult. .PP Mixin::ExtraFields provides a simple way to add an arbitrary number of stashes for named data. These data can be stored in the object, in a database, or anywhere else. The storage mechanism is abstracted away from the provided interface, so one storage mechanism can be easily swapped for another. Multiple ExtraFields stashes can be mixed into one class, using one or many storage mechanisms. .SH "PERL VERSION" .IX Header "PERL VERSION" This library should run on perls released even a long time ago. It should work on any version of perl released in the last five years. .PP Although it may work on older versions of perl, no guarantee is made that the minimum required version will not be increased. The version may be increased for any reason, and there is no promise that patches will be accepted to lower the minimum required perl. .SH "MIXING IN" .IX Header "MIXING IN" To create a stash of extra fields, just \f(CW\*(C`use\*(C'\fR Mixin::ExtraFields and import the \f(CW\*(C`fields\*(C'\fR group like this: .PP .Vb 1 \& use Mixin::ExtraFields \-fields => { driver => \*(AqSomeDriver\*(Aq }; .Ve .PP The only argument required for the group is \f(CW\*(C`driver\*(C'\fR, which names the driver (storage mechanism) to use. For more information, see \*(L"Specifying a Driver\*(R", below. .PP Other valid arguments are: .PP .Vb 2 \& id \- the name of the method to call on objects to get their unique identifier \& default: id; an explicit undef will use each object\*(Aqs reference addr \& \& moniker \- the name to use in forming mixed\-in method names \& default: extra .Ve .SS "Specifying a Driver" .IX Subsection "Specifying a Driver" The \f(CW\*(C`driver\*(C'\fR argument can be given as either a driver identifier or a reference to a hash of options. If given as a hash reference, one of the entries in the hash must be \f(CW\*(C`class\*(C'\fR, giving the driver identifier for the driver. .PP A driver identifier must be either: .IP "\(bu" 4 an object of a class descended from the driver base class .IP "\(bu" 4 a partial class name, to follow the driver base class name .IP "\(bu" 4 a full class name, prepended with + .PP The driver base class is provided by the \f(CW"driver_base_class"\fR method. In almost all cases, it will be \f(CW\*(C`Mixin::ExtraFields::Driver\*(C'\fR. .SH "GENERATED METHODS" .IX Header "GENERATED METHODS" The default implementation of Mixin::ExtraFields provides a number of methods for accessing the extras. .PP Wherever \*(L"extra\*(R" appears in the following method names, the \f(CW\*(C`moniker\*(C'\fR argument given to the \f(CW\*(C`fields\*(C'\fR group will be used instead. For example, if the use statement looked like this: .PP .Vb 1 \& use Mixin::ExtraFields \-fields => { moniker => \*(Aqinfo\*(Aq, driver => \*(AqHashGuts\*(Aq }; .Ve .PP \&...then a method called \f(CW\*(C`exists_info\*(C'\fR would be generated, rather than \&\f(CW\*(C`exists_extra\*(C'\fR. The \f(CW\*(C`fields\*(C'\fR group also respects renaming options documented in Sub::Exporter. .SS "exists_extra" .IX Subsection "exists_extra" .Vb 1 \& if ($obj\->exists_extra($name)) { ... } .Ve .PP This method returns true if there is an entry in the extras for the given name. .SS "get_extra" .IX Subsection "get_extra" .SS "get_detailed_extra" .IX Subsection "get_detailed_extra" .Vb 1 \& my $value = $obj\->get_extra($name); \& \& my $value_hash = $obj\->get_detailed_extra($name); .Ve .PP These methods return the entry for the given name. If none exists, the method returns undef. The detailed version of this method will return a hashref describing all information available about the entry. While this information is driver-specific, it is required to have an entry for the key \f(CW\*(C`entry\*(C'\fR, providing the value that would have been returned by \f(CW\*(C`get_extra\*(C'\fR. .SS "get_all_extra" .IX Subsection "get_all_extra" .SS "get_all_detailed_extra" .IX Subsection "get_all_detailed_extra" .Vb 1 \& my %extra = $obj\->get_all_extra; \& \& my %extra_hash = $obj\->get_all_detailed_extra; .Ve .PP These methods return a list of name/value pairs. The values are in the same form as those returned by the get-by-name methods, above. .SS "get_all_extra_names" .IX Subsection "get_all_extra_names" .Vb 1 \& my @names = $obj\->get_all_extra_names; .Ve .PP This method returns the names of all existing extras. .SS "set_extra" .IX Subsection "set_extra" .Vb 1 \& $obj\->set_extra($name => $value); .Ve .PP This method sets the given extra. If no entry existed before, one is created. If one existed for this name, it is replaced. .SS "delete_extra" .IX Subsection "delete_extra" .Vb 1 \& $obj\->delete_extra($name); .Ve .PP This method deletes the named entry. After deletion, no entry will exist for that name. .SS "delete_all_extra" .IX Subsection "delete_all_extra" .Vb 1 \& $obj\->delete_all_extra; .Ve .PP This method deletes all entries for the object. .SH "SUBCLASSING" .IX Header "SUBCLASSING" Mixin::ExtraFields can be subclassed to produce different methods, provide different names, or behave differently in other ways. Subclassing Mixin::ExtraFields can produce many distinct and powerful tools. .PP None of the generated methods, above, are implemented in Mixin::ExtraFields. The methods below are its actual methods, which work together to build and export the methods that are mixed in. These are the methods you should override when subclassing Mixin::ExtraFields. .PP For information on writing drivers, see Mixin::ExtraFields::Driver. .SS "default_moniker" .IX Subsection "default_moniker" This method returns the default moniker. The default default moniker defaults to the default \*(L"extra\*(R". .SS "methods" .IX Subsection "methods" This method returns a list of base method names to construct and install. These method names will be transformed into the installed method names via \&\f(CW"method_name"\fR. .PP .Vb 1 \& my @methods = Mixin::ExtraFields\->methods; .Ve .SS "method_name" .IX Subsection "method_name" .Vb 1 \& my $method_name = Mixin::ExtraFields\->method_name($method_base, $moniker); .Ve .PP This method returns the method name that will be installed into the importing class. Its default behavior is to join the method base (which comes from the \&\f(CW"methods"\fR method) and the moniker with an underscore, more or less. .SS "driver_method_name" .IX Subsection "driver_method_name" This method returns the name of the driver method used to implement the given method name. This is primarily useful in the default implementation of MixinExtraFields, where there is a one-to-one correspondence between installed methods and driver methods. .PP Changing this method could very easily cause incompatibility with standard driver classes, and should only be done by the wise, brave, or reckless. .SS "gen_fields_group" .IX Subsection "gen_fields_group" .Vb 1 \& my $sub_href = Mixin::ExtraFields\->gen_fields_group($name, \e%arg, \e%col); .Ve .PP This method is a group generator, as used by Sub::Exporter and described in its documentation. It is the method you are least likely to subclass. .SS "build_method" .IX Subsection "build_method" .Vb 1 \& my $code = Mixin::ExtraFields\->build_method($method_name, \e%arg); .Ve .PP This routine builds the requested method. It is passed a method name in the form returned by the \f(CW\*(C`methods\*(C'\fR method and a hashref of the following data: .PP .Vb 3 \& id_method \- the method to call on objects to get their unique id \& driver \- the storage driver \& moniker \- the moniker of the set of extras being built .Ve .PP \&\fBNote!\fR The values for the above arguments are references to the values you'd expect. That is, if the id method is \*(L"foo\*(R" you will be given an reference to the string foo. (This reduces the copies of common values that will be enclosed into generated code.) .SS "default_driver_arg" .IX Subsection "default_driver_arg" .Vb 1 \& my $arg = Mixin::ExtraFields\->default_driver_arg; .Ve .PP This method a default value for the \f(CW\*(C`driver\*(C'\fR argument to the fields group generator. By default, this method will croak if called. .SS "build_driver" .IX Subsection "build_driver" .Vb 1 \& my $driver = Mixin::ExtraFields\->build_driver($arg); .Ve .PP This method constructs and returns the driver object to be used by the generated methods. It is passed the \f(CW\*(C`driver\*(C'\fR argument given in the importing code's \f(CW\*(C`use\*(C'\fR statement. .SS "driver_base_class" .IX Subsection "driver_base_class" This is the name of the name of the class which drivers are expected to subclass. By default it returns \f(CW\*(C`Mixin::ExtraFields::Driver\*(C'\fR. .SH "TODO" .IX Header "TODO" .IP "\(bu" 4 handle invocants without ids (classes) and drivers that don't need ids .SH "AUTHOR" .IX Header "AUTHOR" Ricardo Signes .SH "CONTRIBUTORS" .IX Header "CONTRIBUTORS" .IP "\(bu" 4 Ricardo \s-1SIGNES\s0 .IP "\(bu" 4 Ricardo Signes .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" This software is copyright (c) 2022 by Ricardo Signes. .PP This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.