Subject: | add_relname does not add object if relationship list is still undefined |
Date: | Tue, 25 Nov 2014 14:33:55 +0100 |
To: | bug-Rose-DB-Object [...] rt.cpan.org |
From: | Moritz Bunkus <m.bunkus [...] linet-services.de> |
Hey,
We noticed this with a one-to-many relationship. Let's assume you have a
customer with many contacts. The classes are named
MyDB::Customer and MyDB::Contact, and inside MyDB::Customer there's the
normal __PACKAGE__->add_relationship(…) with 'contacts' being the name.
The problem is the following:
my $customer = MyDB::Customer->new;
$customer->add_contacts(MyDB::Contact->new);
print scalar(@{ $customer->contacts || [] }); # this will output 0
After adding the contact the contact will not show up in
$customer->contacts until you save the $customer. Instead
$customer->contacts returns undef.
The same happens with existing customers if you forcefully unset the
relationship before:
my $customer = MyDB::Customer->new;
$customer->contacts(undef);
$customer->add_contacts(MyDB::Contact->new);
print scalar(@{ $customer->contacts || [] }); # this will output 0
You can circumvent the whole sharade if you forcefully set the
relationship to an empty array reference. The first example now looks
like this:
my $customer = MyDB::Customer->new(contacts => []);
$customer->add_contacts(MyDB::Contact->new);
print scalar(@{ $customer->contacts || [] }); # this will output 1
This is extremely unpredictable behavior and makes working with RDBO as
an object system pretty nasty; point in case: we've just spent roughly
three hours digging through Rose's code in order to track down why it
happens.
The culprit seems to be the way Rose handles the local cache of
add_on_save interfaces. As far as I can tell all new additions seem to
be saved in a post-save hook in $self->{ON_SAVE_ATTR_NAME()}{post} and
_additionally_ also in $self->{$key}, but only if that already exists.
Since $self->{$key} will also get cleared when calling $obj->rel(undef), the
add_on_save interface stops working there, too.
Kind regards,
Moritz Bunkus
--
Dipl.-Inform. Moritz Bunkus
Geschäftsführer/CTO
LINET Services GmbH | Cyriaksring 10a | 38118 Braunschweig
Tel. 0531-180508-0 | Fax 0531-180508-29 | http://www.linet-services.de
LINET in den sozialen Netzwerken:
https://twitter.com/linetservices | https://www.facebook.com/linetservices
Wissenswertes aus der IT-Welt: http://www.linet-services.de/blog/
Geschäftsführung: Moritz Bunkus, Philip Reetz und Timo Springmann
HR B 9170 Amtsgericht Braunschweig
USt-IdNr. DE 259 526 516
Message body not shown because it is not plain text.