NAME
DBIx::DBO2::Fields - Construct methods for database fields
SYNOPSIS
package MyCDs::Disc;
use DBIx::DBO2::Record '-isasubclass';
use DBIx::DBO2::Fields (
{ name => 'id', field_type => 'number', required => 1 },
{ name => 'name', field_type => 'string', length => 64, required => 1 },
{ name => 'year', field_type => 'number' },
{ name => 'artist', field_type => 'number' },
{ name => 'genre', field_type => 'number' },
);
1;
DESCRIPTION
This package creates methods for DBIx::DBO2::Record objects.
It's based on Class::MakeMethods::Template.
Accessing Field Attributes
Calling ->fields()
on a class or instance returns a hash of field-name => field-attribute-hash pairs.
my %fields = BD::Customer::Account->fields();
foreach my $fieldname ( sort keys %fields ) {
my $field = $fields{ $fieldname };
print "$fieldname is a $field->{meta_type} field\n";
print " $fieldname is required\n" if ( $field->{required} );
print " $fieldname max length $field->{length}\n" if ( $field->{length} );
}
You can also pass in a field name to retrieve its attributes.
print BD::Customer::Account->fields('public_id')->{'length'};
The results of ->fields()
includes field information inherited from superclasses. To access only those fields declared within a particular class, call ->class_fields()
instead.
STRING FIELDS
Field Type string
Generates methods corresponding to a SQL varchar column.
Default Interface
The general usage for a string field is:
use DBIx::DBO2::Fields (
string => 'x',
);
This declaration will generate methods to support the following interface:
$record->x() : value
Returns the value of field x for the given record.
$record->x( value )
Sets the value of field x for the given record.
$record->x_invalid() : fieldname => error_message, ...
Check for any error conditions regarding the current value of field x. See Validation, below.
Validation
String fields provide basic error-checking for required values or text that is too long to fit into the associated database column.
You may specify the length of the column and whether a field is required in your field declaration:
use DBIx::DBO2::Fields (
string => '-required 1 -length 64 x',
string => '-required 0 -length 255 y',
);
If you leave the required and length attributes undefined, an attempt will be made to detect them automatically, by checking the database table associated with the current object for a column whose name matches the field's.
use DBIx::DBO2::Fields (
string => 'x',
string => 'y',
);
create table xyzzy (
x varchar(64) not null,
y varchar(255)
);
The --init_and_get Interface
The string field also supports the following declaration for values which only need to be calculated once:
use DBIx::DBO2::Fields (
string => '--init_and_get x',
);
$record->x() : value
Returns the value of field x for the given record.
If the value of field x is undefined, it first calls an initialization method and stores the result. The default it to call a method named init_x, but you can override this by providing a different value for the init_method attribute.
use DBIx::DBO2::Fields ( string => '--init_and_get -init_method find_spot x', );
Or equivalently, and perhaps more readably:
use DBIx::DBO2::Fields ( string => [ '--init_and_get', x, { init_method => 'find_spot' } ], );
Field Type phone_number
Identical to the string type.
Field Type post_code
Identical to the string type.
Field Type state_province
Identical to the string type.
Field Type email_addr
Identical to the string type.
Field Type creditcardnumber
If you declare the following:
use DBIx::DBO2::Fields (
creditcardnumber => "ccnum",
);
You can now use these methods:
# Set and get raw value
$customer->ccnum('4242424242424242');
$customer->ccnum() eq '4242424242424242';
# Analyze card number
$customer->ccnum_checksum() == 1;
$customer->ccnum_flavor() eq 'VISA card';
# Opaque readable value for display
$customer->ccnum_readable() eq '************4242';
# Setting the readable value to the prior opaque value has no effect
$customer->ccnum_readable('************4242');
$customer->ccnum() eq '4242424242424242';
# But setting the readable value to another value overwrites the contents
$customer->ccnum_readable('1234-5678-9101-1213');
$customer->ccnum() eq '1234-5678-9101-1213';
# Recognize bogus cards by the following characteristics...
$customer->ccnum_checksum() == 0;
$customer->ccnum_flavor() eq 'Unrecognized';
$customer->ccnum_readable() eq '1234-5678-9101-1213';
NUMBER FIELDS
Field Type number
Generates methods corresponding to a SQL int or float column.
The general usage for a number field is:
use DBIx::DBO2::Fields (
number => 'x',
);
This declaration will generate methods to support the following interface:
$record->x() : value
Returns the value of field x for the given record.
$record->x( value )
Sets the value of field x for the given record.
$record->x_readable() : value
Returns the value of field x for the given record formatted for display, including commas for thousands separators.
$record->x_readable( value )
Sets the value of field x for the given record from a possibly formatted value.
$record->x_invalid() : fieldname => error_message, ...
Check for any error conditions regarding the current value of field x. See Validation, below.
Validation
Number fields provide error-checking for required values or values which are not numeric.
You may specify whether a field is required or allow this to be detected based on whether the corresponding database column allows null values.
The -init_and_get Interface
The number field also supports the -init_and_get provided by the string field type.
Field Type timestamp
Generates methods corresponding to a SQL int column storing a date and time in Unix seconds-since-1970 format.
Default Interface
The general usage for a timestamp field is:
use DBIx::DBO2::Fields (
timestamp => 'x',
);
This declaration will generate methods to support the following interface:
$record->x() : value
Returns the raw numeric value of field x for the given record.
$record->x( value )
$record->x( readable_value )
Sets the value of field x for the given record. You may provide either a raw numeric value or a human-entered formatted value.
$record->touch_x()
Sets the value of field x to the current date and time.
$record->x_readable() : readable_value
Returns the value of field x formatted for display.
$record->x_readable(format_string) : readable_value
Returns the value of field x formatted in particular way. (See Data::Quantity::Time::Timestamp for supported formats.)
$record->x_obj() : quantity_object
Gets the value of field x as a Data::Quantity::Time::Timestamp object.
$record->x_invalid() : fieldname => error_message, ...
Inherited from the number field.
Field Type julian_day
Generates methods corresponding to a SQL int column storing a date in the Julian days-since-the-invention-of-fire format.
Default Interface
The general usage for a julian_day field is:
use DBIx::DBO2::Fields (
julian_day => 'x',
);
This declaration will generate methods to support the following interface:
$record->x() : value
Returns the raw numeric value of field x for the given record.
$record->x( value )
$record->x( readable_value )
Sets the value of field x for the given record. You may provide either a raw numeric value or a human-entered formatted value.
$record->touch_x()
Sets the value of field x to the current date.
$record->x_readable() : readable_value
Returns the value of field x formatted for display.
$record->x_readable(format_string) : readable_value
Returns the value of field x formatted in particular way. (See Data::Quantity::Time::Date for supported formats.)
$record->x_obj() : quantity_object
Gets the value of field x as a Data::Quantity::Time::Date object.
$record->x_invalid() : fieldname => error_message, ...
Inherited from the number field.
Field Type currency_uspennies
Generates methods corresponding to a SQL int column storing a US currency value in pennies.
Default Interface
The general usage for a currency_uspennies field is:
use DBIx::DBO2::Fields (
currency_uspennies => 'x',
);
This declaration will generate methods to support the following interface:
$record->x() : value
Returns the raw numeric value of field x for the given record.
$record->x( value )
Sets the raw numeric value of field x for the given record.
$record->x_readable() : readable_value
Returns the value of field x formatted for display.
$record->x_readable(readable_value)
Set the value of x based on a human-entered value
$record->x_invalid() : fieldname => error_message, ...
Inherited from the number field.
Field Type saved_total
Used to store numeric values which only have to be calculated when the related records change.
A declaration of
use DBIx::DBO2::Fields (
saved_total => 'x',
);
Is equivalent to the following method definitions:
# Recalculate if status_is_cart; else return previously stored value
sub x {
my $self = shift;
if ( $self->status_is_cart() ) {
$self->{x} = $self->init_x();
} else {
$self->{x};
}
}
# Recalculate and store the value.
sub reset_x {
my $self = shift;
$self->{x} = $self->init_x();
}
# Is our stored value out of synch with current calculations?
sub x_difference {
my $self = shift;
$self->init_x() - $self->{x};
}
You are expected to provide an 'init_x' method which calculates and returns the value, but does not save it.
Field Type saved_total_uspennies
Like saved_total, but also has a read-only *_readable method that provides US Currency formatting.
DATABASE-ORIENTED FIELDS
Field Type unique_code
Used to generate and store a unique code for this object.
The identifiers generally look like 'QX3P6N' or the like -- a mix of the digits from 0 to 9 and upper case consonants (skipping the vowels to avoid confusion between 0/O and 1/I, and to avoid constructing real words). The size is controlled by the "length" meta-method attribute.
Here's a sample declaration:
package Acme::Order::Order;
use DBIx::DBO2::Fields (
"unique_code --length 6 => 'public_id',
);
This field is automatically assigned and confirmed to be unique when the record is inserted.
Here's how you retrieve a specific row:
my $pubid = 'QX3P6N';
$order = Acme::Order::Order->fetch_public_id( $pubid );
With 41 possible characters, a length of 3 gives 68,921 choices, 4 gives 2,825,761, 6 gives 4,750,104,241, and 8 gives 7,984,925,229,121.
Field Type foreign_key
Generates methods corresponding to a SQL int or varchar column storing a value which corresponds to the primary key of a related record from another table.
Default Interface
The general usage for a foreign_key field is:
use DBIx::DBO2::Fields (
foreign_key => 'x',
);
This declaration will generate methods to support the following interface:
$record->x_id() : value
Returns the raw numeric value of field x_id for the given record.
$record->x_id( value )
Sets the raw numeric value of field x_id for the given record.
$record->x() : related_object
Fetches and returns the related record.
If the x_id value is empty, or if there is not a record with the corresponding value in the related table, returns undef.
$record->x( related_object )
Sets the raw numeric value of field x_id based on the corresponding field in the related object.
$record->x_required() : related_object
Fetches and returns the related record, in a case where your code depends on it existing, generally because it calls additional methods without checking the result.
If the x_id value is empty, or if there is not a record with the corresponding value in the related table, croaks with a fatal exception. This makes it easier to spot the problem then Perl's generic "can't call method on undefined value" message.
$record->x_invalid() : fieldname => error_message, ...
If the field is marked required (or the underlying column is defined as not null), reports an error for missing values.
If a value is provided, attempts to fetch the associated record and reports an error if can not be found.
Attributes
hash_key - defaults to *_id
related_class
related_id_method
Example
package EBiz::Order::Order;
use DBIx::DBO2::Fields (
foreign_key => { name=>'account', related_class => 'Account' },
);
...
$order->account_id( 27 );
print $order->required_account->email();
Field Type line_items
Generates methods to retrieve records from another table which have a foreign_key relationship to the current record. Depends on there being a primary key column, but does not require a separate database column of its own.
Default Interface
The general usage for a line_items field is:
package Y;
use DBIx::DBO2::Fields (
line_items => { name=>'x', 'related_field'=>'y_id', related_class=>'X' },
);
This declaration will generate methods to support the following interface:
$record->x() : related_objects
Fetches the related records. Returns a RecordSet.
$record->x( rel_col => rel_value, ...) : related_objects
Fetches a subset of the related records which also meet the indicated criteria. Returns a RecordSet.
$record->count_x()
Returns the number or related records.
$record->new_x() : related_object
Creates and returns a new related record, setting its foreign key field to refer to our record's ID.
(Note that the record is created but not inserted; you need to call ->save() yourself.)
$record->delete_x()
Deletes all of the related records.
You can also specify an array-ref value for the default_criteria attribute; if present, it is treated as a list of fieldname/value pairs to be passed to the fetch and new methods of the related class.
CODE-ORIENTED FIELDS
The below types are for internal use and do not correspond to SQL columns.
Field Type alias
use DBIx::DBO2::Fields (
alias => [ 'x' => 'y' ],
);
This declares a method ->x() that simply calls method ->y() and passes along all of its arguments.
Field Type forward
Local alias for the Universal:forward_methods method generator.
Creates a method which delegates to an object provided by another method.
Example:
use DBIx::DBO2::Fields
forward => [
[ 'w' ], { target=> 'whistle' },
[ 'x', 'y' ], { target=> 'xylophone' },
{ name=>'z', target=>'zither', target_args=>[123], method_name=>do_zed },
];
Example: The above defines that method w
will be handled by the calling w
on the object returned by whistle
, whilst methods x
and y
will be handled by xylophone, and method z
will be handled by calling do_zed
on the object returned by calling zither(123)
.
Attributes: The following additional attributes are supported:
- target
-
Required. The name of the method that will provide the object that will handle the operation.
- target_args
-
Optional ref to an array of arguments to be passed to the target method.
- method_name
-
The name of the method to call on the handling object. Defaults to the name of the meta-method being created.
TO DO
Resolve differing approaches to setting values from human-entered formatted values. Current interface is:
CHANGES
2002-01-17 Simon: Update of Fields to use new version of Class::MakeMethods.
2001-04-09 Simon: Added line_items attrib: default_criteria=>[field=>value,...]
2001-02-07 Simon: Completed fields() method, and improved column attr detection.
2001-01-30 Simon: Added _readable method for all number fields (for ',000's).
2001-01-29 Simon: Filled in missing chunks of documentation.
2001-01-29 Simon: Added *_invalid methods and column-info detection.
2001-01-20 Simon: Added saved_total_uspennies
2001-01-16 Simon: Added saved_total
2000-12 Simon: Added currency_uspennies, timestamp, and julian_day types
2000-12 Simon: Added foreign_key and line_items types
2000-08-04 Simon: Moved package into EBiz::Database.
2000-03-30 Simon: Julian day readable now calls method to access value.
2000-03-10 Simon: Added get_and_set, get_set_filter.
2000-03-06 Simon: Added get_set_alias
2000-02-29 Simon: Created.
COPYRIGHT
Copyright 2000, 2001 Evolution Online Systems, Inc.
You may use, modify, and distribute this software under the same terms as Perl.