[Dbix-class] object as a value of result_class (resultset_class)

Roman Daniel roman.daniel at davosro.cz
Sat Sep 24 19:31:15 GMT 2011


>    Roman> sub inflate_result {
>    Roman>      my ($this, $result_source, $me, $prefetch) = @_;
>
>    Roman>      my $subclass = $me->{something} eq 'anything' ?
>    Roman> 'MySchema::Result::Person::Worker':
>    Roman> 'MySchema::Result::Person::Student';
>    Roman>      return $subclass->inflate_result($result_source, $me, $prefetch);
>    Roman> }
>
> That approach will be a nightmare to maintain. For starters, you will
> have to run everything inside transactions to guarantee that the value
> of $me->{something} doesn't change in the database, throughout the life
> of the inflated object. If the inflated object writes any changes to
> that column, you will have to rebless the object. This will require you
> to cross-check the inflator to make sure you're not writing onto a
> column that warrants a rebless. You can automate that, of course, but
> it'll become quite hard to maintain code where objects keep changing
> classes magically behind the scenes. You can of course, abstract the
> objects and not make any assumptions about the specific classes of the
> objects you're working with, but then what's the benefit of reblessing?
>
> You're better off by creating three tables, a person table, and
> worker/student tables containing the specific data and a 1-1
> relationship to the person table. This approach has a lot less caveats
> than the one you're proposing.

Sorry, but your comment about maintenance nightmare is irrelevant.
Usually my column 'something' is called 'class' and is immutable. When
I create the object I know whether I create Student or Worker. The
example above can be rewritten as

my $subclass = 'Me::Schema::Result::Person::'. $me->{class};
return $subclass->inflate_result($result_source, $me, $prefetch);

Also this approach is by no means mutually exclusive with your three
tables, but it is complementing (I use extension tables, I have one
for almost each 'class'). If I load the object from db and it is the
instance of MySchema::Result::Person::Student, in application logic
written in MySchema::Result::Person::Student I can use student
relationship to other table, while in MySchema::Result::Person::Worker
I will use worker relationship.

If you load MySchema::Result::Person instance from database how do you
know which (mutually exclusive) relationship you should use? Here you
have 2 of them, but when do you have 20 types of person?

> Neil's suggestions are the best approaches.

What are Neil's suggestions? I don't argue. Just give me the 2 lines
of code clue about resultset processors.



More information about the DBIx-Class mailing list