Ford & Mason Ltd
HOME
ABOUT
CONTACT
RESOURCES
ADVERTISING


NAME

Tie::SentientHash - Perl module implementing intelligent objects


SYNOPSIS

  use Tie::SentientHash;

  $hashref = new Tie::SentientHash $meta_data, $initial_data;
  $untiedhash = $hashref->export;
  $metadata   = $hashref->_metadata;

  $hashref->{key} = 'value';
  $hashref->{key1}{key2} = $value;
  $value2 = $hashref->{key};
  undef $hashref;


DESCRIPTION

The Tie::SentientHash package provides intelligent objects. The objects are represented as hashes which:

  • provide read-only elements

  • provide 'special' elements that are handled by user-supplied functions

  • disallow changes to the data as specified by metadata

  • track changes and call a 'commit changes' function when the object is destroyed

References to scalars, arrays and hashes can be stored in hash elements in which case the referenced object is tied to an internal class of the appropriate type (Tie::SentientHash::NestedHash, ::NestedArray or ::NestedScalar), so that changes to the nested data structures can be tracked.

The constructor is invoked with two hash references: the first contains metadata and the second the initial data values. The metadata hash may contain the following flags:

READONLY

a list of hash entries that are read-only (read-only elements cannot be modified -- except by special element handlers -- or deleted and are not deleted when the CLEAR method is called)

SPECIAL

a hash of name/subroutine-refs pairs that specifies elements that are handled specially (special elements also cannot be deleted). The user function is called both for STORE (with four arguments) and for FETCH (with three arguments). The arguments are: a reference to the metadata hash, a reference to the data hash, the element key and if the funtion is being called for a STORE operation, the value to be stored. SPECIAL elements can be used to implement calculated attributes.

TRACK_CHANGES

flag to indicate that the class should keep track of the keys of modified (top-level) hash elements

COMMIT_SUB

a reference to a subroutine to commit changes (called with a reference to the data hash and a reference to the metadata hash)

FORBID_INSERTS

forbid inserts into hash and sub-hashes/arrays

FORBID_DELETES

forbid deletes from hash

FORBID_CHANGES

forbid any changes

Trying to change an object in a way that is forbidden by the metadata will cause the module to croak.

Changes are only tracked at the top level.


EXAMPLE

I use Tie::SentientHash as the basis for implementing persistent objects in my CGI/mod_perl scripts. The details of reading and writing the objects from and to the database is handled by a class, but neither the class nor the high level code needs to keep track of whether the object has been changed in any way.

For example if you had a pay per view system of some kind you could have a script that contained the following fragment:

   sub pay_per_view ($$) {
     my($cust_id, $cost) = @_;

     my $cust = load Customer $cust_id;
     $cust->{CREDIT} -= $cost;
   }

The customer object would be implemented in a module sketched out below. A commit function is specified on the call to create a new sentient object, and that function will be called when $cust goes out of scope at the end of the pay_per_view function and can write the modified object back to the database. If none of the attributes had been modified then the commit function would not be invoked.

   package Customer;

   sub load ($$) {
     my ($class, $cust_id) = @_;
     my $data = {};

     # read customer data from a database into $data

     my $meta = { COMMIT_SUB     => \&_commit,
                  READONLY       => [ qw( CUST_ID ) ],
                  FORBID_INSERTS => 1 };

     return bless new Tie::SentientHash($meta, $data), $class;
   }

   sub _commit ($$) {
     my ($meta, $data) = @_;

     # As we have been called, something has changed.  The names of
     # the modified fields are the keys of $meta->{MODIFIED}.  We had
     # better write the data back out to the database.

}


RESTRICTIONS

Full array semantics are only supported for Perl version 5.005.


AUTHOR

Andrew Ford <[email protected]>


SEE ALSO

perl(1).


COPYRIGHT

Copyright 1999 Ford & Mason Ltd. All rights reserved.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

 
Copyright © 1996-2002 Ford & Mason Ltd