[Dbix-class] table-per-subclass - how it works?
Hailin Hu
i at h2l.name
Fri Jun 15 08:49:34 GMT 2012
No, on subclass layer, Host has no relationship with Target.
The idea is a little tricky.
Inheritage is implemented according to the attribute 'parents' instead
of the natural class inheritage.
In class 'Host'
>> sub _build_parents {[qw/target/]}
This declaresd Host's parent as target( the relationship method name ).
Since 'Host' extends 'Base'
>> sub inflate_result {
This would be called when object is inited, which dynamically creates
so-called inherited accessors.
On Fri, Jun 15, 2012 at 5:30 PM, Alex Erzin <eaa-home at yandex.ru> wrote:
> I'm confused with "package Host; extends 'Base';"
> I expect "extends 'Target'", not 'Base'. Is it correct?
>
> 15.06.2012, 12:06, "Hailin Hu" <i at h2l.name>:
>> I have no idea about "standard" solution, but another idea for reference :)
>>
>> Package Base;
>> use base 'DBIx::Class::Core';
>>
>> # parents' name should be a defined has_one or belong_to relationship
>> has 'parents' => (
>> is => 'rw',
>> isa => 'ArrayRef[Str]',
>> builder => _build_parents,
>> );
>>
>> sub inflate_result {
>> my $self = shift;
>> my $ret = $self->next::method( @_ );
>> foreach my $relationship ( @{ $ret->parents } ) {
>> my $parent = $ret->$relationship;
>> my @columns = ... # @columns_in_$parent - @column_in_$ret
>> foreach my $column ( @columns ) {
>> # stolen from DBIx::Class's source
>> no strict 'refs';
>> no warnings 'redefine';
>> my $method = join '::', ref $ret, $column;
>> *$method = Sub::Name::subname( $method, sub {
>> return $ret->$parent->$column;
>> });
>> }
>> }
>> }
>> ...
>>
>> package Target;
>> extends 'Base';
>> ...
>>
>> package Host;
>> extends 'Base';
>> __PACKAGE__->belong_to('target' => 'Target', 'target_id');
>> sub _build_parents {[qw/target/]}
>> ...
>>
>> so just declare the attribute 'parents' in subclass is ok.
>> the task is not typical for me, but interesting.
>>
>> On Fri, Jun 15, 2012 at 3:59 PM, Alex Erzin <eaa-home at yandex.ru> wrote:
>>
>>> Yes, in some cases you are right, but you are saying about "long inheritance chains" and other cases where inheritance is not enought flexible,
>>> but i say about just one case in one place where inheritance is preferred for me, and i try to find solution _how_ to implement inheritance, but not about _why_not_ :)
>>>
>>> 15.06.2012, 10:43, "Ben Tilly" <btilly at gmail.com>:
>>>> The benefits of OOP are mostly in information hiding.
>>>>
>>>> If you're creating a bunch of long inheritance chains, you're probably
>>>> doing OOP poorly. Composition is preferred. And maps *much* more
>>>> naturally onto a relational database.
>>>>
>>>> On Thu, Jun 14, 2012 at 11:37 PM, Alex Erzin <eaa-home at yandex.ru> wrote:
>>>>> Hm... it really works, but where are benefits of OOP? ;)
>>>>> There is no inheritance at all, and to access parent's properties I should call parent directly, so inheritance just replaced with incapsulation, and it's no one what i try to find.
>>>>>
>>>>> Some years ago we have implemented inheritance in ORM in some commercial project in Perl, later I have swithed to java and have found Hibernate it really cool with ORM.
>>>>> But now I have returned to Perl and I think that DBIx::Class can help me with ORM, but right now i'm confused that cannot find "standard" solution for typical task.
>>>>>
>>>>> 15.06.2012, 10:25, "Hailin Hu" <i at h2l.name>:
>>>>>> Is it acceptable like something below
>>>>>>
>>>>>> package Target;
>>>>>> ...
>>>>>> package Host;
>>>>>> ...
>>>>>> __PACKAGE__->belong_to('target' => 'Target', 'target_id');
>>>>>> sub column_only_exists_in_target {
>>>>>> my $self = shift;
>>>>>> return $self->target->column_only_exists_in_target;
>>>>>> }
>>>>>>
>>>>>> well, it is not a good solution, but it could work, I think :)
>>>>>>
>>>>>> On Fri, Jun 15, 2012 at 3:04 PM, Alex Erzin <eaa-home at yandex.ru> wrote:
>>>>>>> Hello,
>>>>>>>
>>>>>>> I need to implement table-per-class inheritance, as it simple made in Hibernate in Java (more details can be found here http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch10.html#inheritance-tablepersubclass),
>>>>>>> but cannot find right way how to do it in DBIx::Class.
>>>>>>>
>>>>>>> For example, I have two objects: Target (with properties ID, Description) and Host (ID, Hostname, IP), Host inherited from Target, and on table-level there are two tables Host and Target, joined by ID field.
>>>>>>>
>>>>>>> CREATE TABLE `mydb`.`target` (
>>>>>>> `target_id` INT NOT NULL ,
>>>>>>> `description` VARCHAR(45) NULL ,
>>>>>>> PRIMARY KEY (`target_id`) )
>>>>>>>
>>>>>>> CREATE TABLE `mydb`.`host` (
>>>>>>> `target_id` INT NOT NULL ,
>>>>>>> `hostname` VARCHAR(45) NULL ,
>>>>>>> `ip` VARCHAR(45) NULL ,
>>>>>>> PRIMARY KEY (`target_id`) ,
>>>>>>> CONSTRAINT `fk_host_target`
>>>>>>> FOREIGN KEY (`target_id` )
>>>>>>> REFERENCES `mydb`.`target` (`target_id` )
>>>>>>> )
>>>>>>>
>>>>>>> How to implemeng there classes Target and Host, so it possible to write
>>>>>>>
>>>>>>> print $target->id(), $targer->description()
>>>>>>> print $host->id(), $host->description(), $host->hostname(), $host->ip()
>>>>>>>
>>>>>>> ?
>>>>>>>
>>>>>>> I have no ideas how to implement inheritance, and all my experiments are failed - from Host i cannot get access to parent properties like description.
>>>>>>> Could you help me please (with examples)?
>>>>>>>
>>>>>>> Thanks.
>>>>>>>
>>>>>>> --
>>>>>>> eaa@
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>>>>>>> IRC: irc.perl.org#dbix-class
>>>>>>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>>>>>>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>>>>>> _______________________________________________
>>>>>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>>>>>> IRC: irc.perl.org#dbix-class
>>>>>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>>>>>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>>>>> --
>>>>> eaa@
>>>>>
>>>>> _______________________________________________
>>>>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>>>>> IRC: irc.perl.org#dbix-class
>>>>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>>>>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>>>> _______________________________________________
>>>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>>>> IRC: irc.perl.org#dbix-class
>>>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>>>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>>> --
>>> eaa@
>>>
>>> _______________________________________________
>>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>>> IRC: irc.perl.org#dbix-class
>>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>>
>> _______________________________________________
>> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
>> IRC: irc.perl.org#dbix-class
>> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
>> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
>
> --
> eaa@
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive: http://www.grokbase.com/group/dbix-class@lists.scsys.co.uk
More information about the DBIx-Class
mailing list