I learned about Class::DBI over the summer, and have really come to love it. Well, almost. The idea is that it’s an OO to RDMS mapper. And a really slick one at that. You basically tell it what table an object should be linked to, and what fields that table has, and what other objects are foreign keys on that table, and it creates all the basic RDMS methods you would want, from create and delete, to search, to getters and setters, to you name it.
However, I’ve been tearing my hair out for several days now with some really nasty problems with it. I’m trying to do something that’s a bit funky, and Class::DBI is making it that much worse.
Basically, I’m trying to do some node/association stuff. So I’ve got one node table, and one association table, with some periphery tables with one-to-one relationships with the main two tables, which provide extra fields for specific node types. So, for instance, there’s a user node, which has a seperate user table.
On the OO side of things, there’s a Node object, and a User object which inherits from Node. The idea is that the User object is a specialized version of a Node row, one in which the type field is set to ‘user’, and for which there’s a matching row in the user table. There’s some special magic using triggers, which reblesses objects into the right subclass when they get hydrated out of the database, as well as some more trigger magic which sets the type field properly.
The problem really stems from the fact that Class::DBI uses Class::Data::Inheritable to store trigger information. The HasA and MightHave relationships use triggers to do inflation properly (so that a createdby foreign key field becomes a User object when the node is hydrated). All the trigger information is stored in a single Class::Data::Inheritable accessor (__triggers).
Class::Data::Inheritable is built such that if a subclass changes the data, it gets it’s own, seperate copy. This is a problem for me, because the various initialization code doesn’t always get called in the same order, and definitely not in an order I have very good control over. Thus, if the User object sets a trigger before the Node object finished setting it’s triggers, the User object never inherits the all of the necessary triggers. Which really sucks.
And it took me many, many hours to figure this out. I guess the upshot is that I now know far more about the perl compilation process than I probably will ever need to again.