[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