Hi Oleg, Thanks for your advice. I've tried this and it might be the way to go for me. Id prefer to be able to have a resultset object for the subclasses as well so that I can do $rs = $schema->resultset('ClassA')->new(...);
That way it would ensure that the only the correct columns were available when creating a new row for classA. I would also be able to search on the subclass columns - why the need to use frozen columns, why cant you just use add_columns to add extra cols to the already defined baseclass ones for the subclass? Maybe this comes down to having just one result_source under the hood. I have managed via a custom resultset object to use set proxy methods at row creation by intercepting the new_result method. sub new_result { my ($self,@args) = @_; #get actual cols for the table my @cols = $self->result_source->columns; # look for provided args that are not in table # assume they are proxied args my %proxyArgs; foreach my $k (keys %{$args[0]}) { if (!grep /$k/, @cols) { $proxyArgs{$k} = delete $args[0]{$k}; } } # create new row my $row = $self->next::method(@args); # set proxied args foreach my $k (keys %proxyArgs) { $row->$k($proxyArgs{$k}); } } with this in place, I can now do: $schema->resultset('SubClass')->create( subClassCol1=> 'xxx', subClassCol2=>'yyy', baseClassCol=> 'zzz'); The subClassCol1 and subClassCol2 live in the sub class's table and the baseClassCol lives in the base class's Table. By this method I also ensure that a base class row exists for every sub class. I need to experiment more, but this should allow me to have Subclass and baseclass resultsets, both searchable on all columns. Just need to ensure I can get the relationships correct to my other objects. ________________________________ From: Oleg Pronin [mailto:syber....@gmail.com] Sent: 22 January 2009 01:40 To: DBIx::Class user and developer list Subject: Re: [Dbix-class] RE: Inheritance question.. 1) DBIx::Class::DynamicSubclass will automaticaly subclass your row object when a) fetched from DB b) created (->new or ->create) c) changed subclassing column For example when type = null row is BaseClass, when type = 1 row is ClassA, when 2 row is ClassB. my $row = $rs->new({type => 1}); # $row is ClassA $row->type(2); #$row is ClassB $row->type(undef); #$row is BaseClass 2) You can set up dynamic columns with subclassing if you use DBIx::Class::DynamicSubclass + DBIx::Class::FrozenColumns. But there is caveat: you will not be able to use 'frozen' columns in WHERE clause in SQL. The idea is: package BaseClass; ->load_components(qw/DynamicSubclass FrozenColumns Core/); ->add_columns(qw/all_columns_that_are_common_to_all_subclasses + type + data/); #data must be of type blob or text (depends on storage engine) ->typecast_map(type => {1 => 'ClassA', 2 => 'ClassB'}); package ClassA; use parent 'BaseClass'; ->add_frozen|dumped|json_columns(data => qw/all_columns_that_are_specific_to_ClassA for_example/); package MyCode; my $row = $rs->create({type => 1}); $row->for_example('hello'); #ok $row->type(2); $row->for_example('hello'); # error $rs->new({ type=> 1, for_example => 'hello' }); #that's ok too This is not ideal mechanism, but it quite useful and it helps me many times. 2009/1/21 Howe, Tom (IDEAS PRACTICE AREAS) <tom.h...@morganstanley.com<mailto:tom.h...@morganstanley.com>> Further to my question on inheritance, I have been trying subclassing and the proxy method options and have a couple of other questions. First, in an attempt to try the single flattened style where all Foo object reside in one table, I tried the cookbook entry on "Dynamic Sub-classing DBIx::Class proxy classes". I set up a db table called foo, created a Foo class with an inflate_result() method and a Foo::Noisy class that inherited from the Foo class. I can now create the Foo object and have it inflate into a Foo::Noisy class. But, I cant get a Foo::Noisy resultset. I thought maybe I could define Foo with only the common columns, then create a Foo::Noisy subclass that would inherit the columns of Foo and then I could create a default value for 'type' and use add_columns() to define the additional NoisyFoo column 'decibels'. But it seems the only resultset I can get is for Foo. So anyone creating objects could inadvertently set a 'colour' for a NoisyFoo or a 'decibel' for ColouredFoo. The second thing I tried was to create 3 separate tables for Foo, NoisyFoo and ColouredFoo. Then I created a Foo::Noisy class with a has_one relationship to the Foo class using a proxy=>[] defined to allow transparent setting/getting of the 'name'. This works to a degree in that I can do : my $nf = $schema->resultset('Foo::Noisy')->create({id=>1, decibels=>110}); $nf->name('mynoisyfoo'); But it fails if I try to do: my $nf = $schema->resultset('Foo::Noisy')->create({id=>1, decibels=>110, name=>'noisyfoo'}); Giving the error: DBIx::Class::ResultSet::create(): No such column name on DB::Foo::Noisy The proxy doesn't seem to be in affect during creation. Also, if I *don't* set the name, I don't get a row in the Foo table. Is there a way to enforce that the row is created? Otherwise, if I want to search for all Foos, I cant do it on the common table. Is there anyway to ensure the Foo row is created and grn can be passed on create? > -----Original Message----- > From: Howe, Tom (IDEAS PRACTICE AREAS) > Sent: 21 January 2009 09:42 > To: DBIx::Class user and developer list > Subject: [Dbix-class] Inheritance question.. > > Class structure is something like this.. > +------+ +------------+ +-------------+ | Bar |---o| Relation |o - - - - - - | Foo |abstract +------+ +------------+ +-------------+class | id | | attrs |o | id | | name | +------------+ \_________ | name | +------+ \ \ +-------------+ \ \___^_____ ^ \ | \ | \ +------------+ +-------------+ \| NoisyFoo | | ColouredFoo | +------------+ +-------------+ | id | | id | | decibels | | color | +------------+ +-------------+ > +-------------+ > > Bar has many Relations > NoisyFoo has many Relations > ColouredFoo has many Relations > Bar many-many NoisyFoos > Bar many-many ColouredFoos > > (Bar many-many Foos?) > > > NoisyFoo and ColouredFoo inherit from Foo > > It actually gets more complicated than this because > - Bar and Foo both inherit from a base object. > - All objects have a unique id are connected via Relation objects > - The relation object also contains levels of inheritance > > I want to be able to do queries like > > 1) Given a Bar, find all related Foo objs > 2) Given a NoisyFoo or Coloured Foo, find all related Bars > 3) For all bars with name matching "%str%" find all NoisyFoos > with decibels > '100' > > Im not sure whether it would be better to > a) retain Foo, NoisyFoo and ColouredFoo as a 3 separate tables, > b) flatten to 2 tables, so NoisyFoo and ColouredFoo get their > own name column > c) flatten all Foos to 1 Foo table and create a Type column > to differentiate. > > > Questions: > > Is it possible to create Foo, NoisyFoo and ColouredFoo as > separate tables (a), then create corresponding DBIx proxy > classes for them in such a way that when I create a new > NoisyFoo row, the 'name' value is automatically entered into > the Foo table? And when I retrieve the row it is > automatically read in from the Foo table? > > > If I were to flatten to 1 table per subclass (b), how would I > write a relationship that enabled me to perform query (1) > above; find all Foos for a given Bar. > -------------------------------------------------------- > > NOTICE: If received in error, please destroy and notify > sender. Sender does not intend to waive confidentiality or > privilege. Use of this email is prohibited when received in error. > > _______________________________________________ > List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class > IRC: irc.perl.org#dbix-class<http://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 > -------------------------------------------------------- NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error. _______________________________________________ List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class IRC: irc.perl.org#dbix-class<http://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 -------------------------------------------------------- NOTICE: If received in error, please destroy and notify sender. Sender does not intend to waive confidentiality or privilege. Use of this email is prohibited when received in error.
_______________________________________________ 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