|
NAMESPOPS::Tie - Simple class implementing tied hash with some goodiesSYNOPSIS# Create the tied hash use SPOPS::Tie; my ( %data ); my @fields = qw( first_name last_name login birth_date ); tie %data, 'SPOPS::Tie', $class, \@fields; # Store some simple properties $data{first_name} = 'Charles'; $data{last_name} = 'Barkley'; $data{login} = 'cb'; $data{birth_date} = '1957-01-19'; # Store a temporary property $data{tmp_rebound_avg} = 11.3; while ( my ( $prop, $val ) = each %data ) { printf( "%-15s: %s\n", $prop, $val ); } # Note that output does not include 'tmp_rebound_avg' >first_name : Charles >login : cb >last_name : Barkley >birth_date : 1957-01-19 print "Rebounding Average: $data{tmp_rebound_avg}\n"; # But you can access it still the same >Rebounding Average: 11.3 DESCRIPTIONStores data for a SPOPS object, and also some accompanying materials such as whether the object has been changed and any temporary variables.Checking Changed StateYou can check whether the data have changed since the last fetch by either calling the method of the SPOPS object (recommended) or asking for the '_changed' key from the "tied()" object:# See if this object has changed if (tied %data){_changed} ) {; ...do stuff... } # Tell the object that it has changed (force) (tied %data){_changed} = 1; Note that this state is automatically tracked based on whether you set any property of the object, so you should never need to do this. See SPOPS for more information about the changed methods. Tracking Temporary VariablesNote that this section only holds true if you have field-checking turned on (by passing an arrayref of fields in the 'field' key of the hashref passed as the second parameter in the "tie" call).At times you might wish to keep information with the object that is only temporary and not supposed to be serialized with the object. However, the 'valid property' nature of the tied hash prevents you from storing information in properties with names other than those you pass into the initial call to tie(). What to do? Have no fear! Simply prefix the property with 'tmp_' (or something else, see below) and SPOPS::Tie will keep the information at the ready for you: my ( %data ); my $class = 'SPOPS::User'; tie %data, 'SPOPS::Tie', $class, [ qw/ first_name last_name login / ]; $data{first_name} = 'Chucky'; $data{last_name} = 'Gordon'; $data{login} = 'chuckg'; $data{tmp_inoculation} = 'Jan 16, 1981'; For as long as the hash %data is in scope, you can reference the property 'tmp_inoculation'. However, you can only reference it directly. You will not see the property if you iterate through hash using keys or each. Lazy LoadingYou can specify you want your object to be lazy loaded when creating the tie interface:my $fields = [ qw/ first_name last_name login life_history / ]; my $params = { is_lazy_load => 1, lazy_load_sub => \&load_my_variables, field => $fields }; tie %data, 'SPOPS::Tie', $class, $params; Storing Information for Internal UseThe final kind of information that can be stored in a SPOPS object is 'internal' information. This is similar to temporary variables, but is typically only used in the internal SPOPS mechanisms -- temporary variables are often used to store computed results or other information for display rather than internal use.For example, the SPOPS::DBI module could allow you to create validating subroutines to ensure that your data conform to some sort of specification: push @{ $obj->{_internal_validate} }, \&ensure_consistent_date; Most of the time you will not need to deal with this, but check the documentation for the object you are using. Field MappingYou can setup a mapping of fields to make an SPOPS object look like another SPOPS object even though its storage is completely different. For instance, say we were tying a legacy data management of system of book data to a website. Our web designers do not like to see FLDNMS LK THS since they are used to the more robust capabilities of modern data systems.So we can use the field mapping capabilities of "SPOPS::Tie" to make the objects more palatable: my $obj = tie %data, 'SPOPS::Tie', 'My::Book', { field_map => { author => 'AUTH', title => 'TTL', printing => 'PNUM', classification => 'CLSF' } }; (See the SPOPS documentation for how to declare this in your SPOPS configuration.) So your web designers can use the objects: print "Book author: $book->{author}\n", "Title: $book->{title}\n"; But the data are actually stored in the object (and retrieved by an "each" query on the object -- be careful) using the old, ugly names 'AUTH', 'TTL', 'PNUM' and 'CLSF'. This can be extremely helpful not only to rename fields for aesthetic reasons, but also to make objects conform to the same interface. Multivalue FieldsSome data storage backends -- such as LDAP -- can store multiple values for a single field, and "SPOPS::Tie" can represent it.Three basic rules when dealing with multivalue fields:
The interface for setting values is somewhat different, so sit up straight and pay attention. (0) Telling SPOPS::Tie my $obj = tie %data, 'SPOPS::Tie', 'My::LDAP::Person', { multivalue => [ 'objectclass' ] }; This means only the field 'objectclass' will be treated as a multivalue field. (1) Creating a new object my $person = My::LDAP::Person->new(); $person->{objectclass} = [ 'inetOrgPerson', 'organizationalPerson', 'person' ]; $person->{sn} = 'Winters'; $person->{givenname} = 'Chris'; $person->{mail} = 'chris@cwinters.com'; $person->save; The property 'objectclass' here is multivalued and currently has three values: 'inetOrgPerson', 'organizationalPerson', and 'person'. (2) Fetching and displaying an object my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); print "Person info: $person->{givenname} $person->{sn} ", "(mail: $person->{mail})\n"; print "Classes: ", join( ', ', @{ $person->{objectclass} } ), "\n"; Displays: > Person info: Chris Winters (mail: chris@cwinters.com) > Classes: inetOrgPerson, organizationalPerson, person Note that if there were no values for defined for "objectclass", the value retrieval would return an arrayref. Value retrievals always return an array reference, even if there are no values. This is to provide consistency of interface, and so you can always use the value as an array reference without cumbersome checking to see if the value is "undef". (3) Setting a single value my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); $person->{objectclass} = 'newSchemaPerson'; $person->save; The property 'objectclass' now has four values: 'inetOrgPerson', 'organizationalPerson', 'person', and 'newSchemaPerson'. (4) Setting all values my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); $person->{objectclass} = [ 'newSchemaPerson', 'reallyNewPerson' ]; $person->save; The property 'objectclass' now has two values: 'newSchemaPerson', 'reallyNewPerson'. (5) Removing one value my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); $person->{objectclass} = { remove => 'newSchemaPerson' }; $person->save; The property 'objectclass' now has one value: 'reallyNewPerson'. my $object_class_thingy = $person->{objectclass}; print "Object class return is a: ", ref $object_class_thingy, "\n"; Displays: > Object class return is a: ARRAY Again: when a multivalued property is retrieved it always returns an arrayref, even if there is only one value. (6) Modifying one value my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); $person->{objectclass} = { modify => { reallyNewPerson => 'totallyNewPerson' } }; $person->save; The property 'objectclass' still has one value, but it has been changed to: 'totallyNewPerson'. Note: you could have gotten the same result in this example by doing: $person->{objectclass} = [ 'totallyNewPerson' ]; $person->save; (7) Removing all values my $person = My::LDAP::Person->fetch( 'chris@cwinters.com' ); $person->{objectclass} = undef; $person->save; The property 'objectclass' now has no values. You can also get the same result with: $person->{objectclass} = []; $person->save; METHODSSee Tie::Hash or perltie for details of what the different methods do.TO DOBenchmarkingWe should probably benchmark this thing to see what it can do BUGSNone known.SEE ALSOperltieCOPYRIGHTCopyright (c) 2001-2004 intes.net, inc.. All rights reserved.This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. AUTHORSChris Winters <chris@cwinters.com>
Visit the GSP FreeBSD Man Page Interface. |