[Catalyst] Template creates objects via belongs_to autovivification
mattrosin at yahoo.com
Wed Jun 13 13:17:33 GMT 2007
I discovered an interesting bug/feature, in which a template seems to be executing an SQL insert without that being intended or even visible in the code! I think it's worth explaining exactly what's going on so please pardon the length.
In my Apache/FastCGI/Catalyst/MySQL/TT/DBIx::Class application (called CatMgr) I have Customer and Transaction objects. An admin portal shows a list of recent transactions, which are created when an Instant Payment Notification from PayPal says a payment was made.
Anyway, the transaction table has a field called customer storing the ID of a record in the customer table. I specify the relation ORMwise in CatMgrDB/Transaction.pm with:
__PACKAGE__->belongs_to( customer => CatMgrDB::Customer );
I decided to be clever (boom) and get the template, which is only handed a resultset with rows from the transaction table, to look up the company name of the associated Customer (r.customer.b_company, where r is a row in the resultset) and not have to make a more complicated search statement in the controller.
The thing is, then I decided to let admins add new transactions without an associated customer, to record in the database transactions that were made offline. Instead of assigning r.customer to the id of the company running the system I just say 0 (not using nulls). What happens is, somehow the template forces Catalyst (DBIx::Class) to create a NEW CUSTOMER if there wasn't one already. This is bad, bad, bad. Every time an admin views the list of transactions, it seems I get 4 blank customer records silently added simultaneously, or maybe even more, depending on what kind of records are shown on the current page it seems. I discovered this by matching the FastCGI error log (which is where the -Debug output goes.. all 300MB of it...) against the modification date of the new customer records.
It seems like I need a cascading_inserts => 0 style attribute here, though I can hack around it but I would like to know what the right way to deal with this. If I can leave the code as is and toggle a single attribute (maybe I should remove that belongs_to or convert it to a might_have?) that would be nice. It seems to be an easy pitfall. I can't find any documentation about a relation forcing objects to autovivify, it seems like a bug. Can anyone comment on this?
Need a vacation? Get great deals
to amazing places on Yahoo! Travel.
More information about the Catalyst