perl-embperl mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Kee Hinckley <>
Subject Re: Subclassing DBIx::Recordset
Date Fri, 21 Nov 2003 09:06:04 GMT
At 8:15 AM +0100 11/19/03, Gerald Richter wrote:
>I would prefer to extent DBIx::Recordset, so it could be easily subclassed.
>Since Terrence is now working on DBIx::Recordset, we hopefully will have a
>new release with patches of the last year incoorporated soon.

Well, you convinced me to give it a try, and it appears to now be 
working.  I want to test it a few more days and then I'll put out the 
patches.  I made the following changes.

- Most of the places where there were calls to DBIx::Recordset::Setup 
were easily replaced with $class or $self -> Setup.  One instance 
(searching on links) had to be replaced with 

- I added three new methods to DBIx:Recordset; RowClass, HashClass 
and CurrRowClass.  (Someday I need to figure out what the distinction 
is between CurrRowClass and RowClass.)  In DBIx::Recordset these 
return 'DBIx::Recordset::Row', 'DBIx::Recordset::Hash', and 
'DBIx::Recordset::CurrRow' respectively.  Subclasses of 
DBIx::Recordset can change them if desired, so long as the return 
value references a subclass of the the base DBIx::Recordset::* 

- I changed any direct class comparisons to ISA comparisons.

So far it seems to work, although I haven't tried subclassing the 
helper classes yet.  I did migrate my encapsulation class 
(DBIx::Objectset) to a subclass of DBIx::Recordset.

One of the interesting things my subclass does is attempt to 
determine the appropriate class based on the table name.  In other 
words, if I have a subclass of DBIx::Objectset called MF::Set and I 
create a new instance of MF::Set using {!Table => "foo"}, then the 
Setup method will look for (in memory, and via "require") 
MF::Set::Foo or MF::Foo before defaulting to a new instance of 
MF::Set.  This allows you to create domain-specific behavior for 
certain tables.  For instance, you could override "Insert" and have 
it check to see if all the arguments that you require have been 
specified.  Or you could cascade an Update so that it updated related 
tables at the same time.  With that model you can do the following 
kinds of things.

*account = MF::Set->Setup({ '!Table' => 'account' });
	# returns an MF::Set::Account object
*user = $account{-user};
	# returns an MF::Set::User object
*article = MF::Set::Article->Setup();
	# the default Setup method will set the !Table value

(None of those examples set the database info because DBIx::Objectset 
specifies the connect string, username, password and related values 
as methods that can be overridden by subclasses to provide default 

My database relationships were getting too complex, especially where 
MySQL doesn't do any cross-table consistency checking, and the 
procedural code was just getting too messy, with different 
dependencies scattered around.  This allows me to encapsulate all of 
the table-specific knowledge in a single object that is tied to that 

Still left to migrate to the new subclass, or possibly into Recordset 
itself are two other features.  "Safe" mode throws an error if you 
try to write or read a fieldname that doesn't exist.  And the other 
option is the ability to trigger function callbacks when certain 
fields are modified.

Kee Hinckley         Next Generation Spam Defense  Writings on Technology and Society

I'm not sure which upsets me more: that people are so unwilling to accept
responsibility for their own actions, or that they are so eager to regulate
everyone else's.

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message