[Dbix-class] Schema reference object disapears from my resultset
when building collections
Jason Wieland
jason-dbix at patnjay.org
Thu Apr 12 16:42:07 GMT 2007
Ash Berlin wrote:
> Jason Wieland wrote:
>> Hello,
>> I hope everyone is having a good day. I've been pulling my hair out
>> about this issue for a while and I hope someone can help me. First let
>> me commend the authors for DBIx, after 8 years of witting sql I'm
>> getting pretty sick of it, thank you.
>>
>> I have a two layered system:
>> first perl module called pcGame.pm that handles business logic
>> and a second module called PocketCombat.pm that handles the data access
>> layer
>>
>> OO'ish style to separate the Data Objects from the Business Objects.
>> Obviously I integrated DBIx into my Data Objects. Everything was going
>> fine until I started building collections (object factories).
>>
>> I want to gather all games from a certain customer (similar to gathering
>> all books from an author, from the common examples).
>>
>> pcGame.pm:
>> .....
>> $games = PocketDO::PocketCombat->find( -owner => $profile );
>> ......
>>
>> ($games is an array ref of all the game objects that are owned by a
>> profile)
>>
>> PocketCombat.pm
>> .....
>> my $rs = $self->_dataRs->search(
>> {
>> 'me.profile' => $in{-owner}->id
>> },
>> );
>>
>> my @games;
>> while (my $game_rs = $rs->next) {
>> my $game = __PACKAGE__->_new($pkg);
>> $game->{data} = $game_rs;
>> $game->{id} = $game->{data}->gameid;
>> push @games, $game;
>> }
>> return \@games;
>>
>>
>> When I start to query the data in pcGame.pm I get this error
>> Can't call method "source" on an undefined value at
>> /usr/lib/perl5/site_perl/5.8.8/DBIx/Class/ResultSource.pm line 907.
>>
>> Everything in $game->{data} works great until it is returned back to
>> pcGame.pm
>>
>> It looks like part of the resultset data structure vanishes, in
>> particular the 'schema' object reference.
>> This is what a Dumper of the first element of the array looks like
>> before it is returned:
>> http://www.patnjay.org/pre_return_datastructure.txt
>> and right after it is returned it looks like this
>> http://www.patnjay.org/post_return_datastructure.txt
>>
>> The only change between the two dumps is that 'schema' => undef
>>
>> I have found two roundabout solutions that I don't like. If in the Data
>> layer while looping through the rs->next, I call all my accessors that I
>> plan on using
>> $game->type;
>> $game->state;
>> .....
>> If I preload all this data it will be accessible from the pcGame.pm
>> However this make maintenance a nightmare.
>>
>> The second (crappy) solution is to clone the resultset as I add it the
>> object
>> $game->{data} = clone($game_rs);
>> instead of
>> $game->{data} = $game_rs;
>> Clone coming from http://search.cpan.org/~rdf/Clone-0.22/Clone.pm
>>
>> I would rather not do this because Clone has other issues that I would
>> need to deal with.
>>
>> Anyone see this issue before? Or have any suggestions.
>>
>> Thanks,
>>
>> Jason Wieland
>>
>
> How are you populating $self->_dataRs? Are you a using
> Storable::clone/freeze/thaw somewhere?
>
> If this is the case, you will _have_ to reset the schema reference
> after thaw/clone.
>
> We probably need to 1) document this, and 2) provide better hooks to
> reset the schema.
>
> Ash
>
I don't use Storable/clone/freeze/thaw operation on the resultsource
storage.
sub _dataRs {
my $self = shift;
return $self->gameSchema->resultset('Game');
}
and then gameSchema is inherited from the base class (PocketDO.pm)
sub gameSchema {
my $self = shift;
if (! $self->{schema}) {
$self->{schema} =
Schema::GameAPI->connect("dbi:SQLite:dbname=/var/www/lib/gameapi/data/gameapi.db",
"",
"",
{AutoCommit => 1}
);
}
return $self->{schema};
}
I would rather not use Storable::clone/freeze/thaw anywhere in the
application. I've just used clone now in order to save the Schema
reference.
Thanks you for your quick response
Jason
More information about the Dbix-class
mailing list