[Dbix-class] overriding create [was role of result class? ]

Richard Jolly Richard.Jolly at bbc.co.uk
Wed Mar 8 12:35:29 CET 2006


 
Jess Robinson wrote:

> On Tue, 7 Mar 2006, Richard Jolly wrote:
> 
> > I'm trying to understand the role of the result_class, and 
> I have what 
> > I think are naive questions.
> >
> > In a schema with
> >
> >   My::Schema::Artist
> >
> >   ...
> >
> >   my $schema->resultset('Artist')->search();
> >   My::Artist->search();
> >
> > Are the last two lines identical? Why is the first the 
> preferred syntax?
> 
> Whether those two are identical or not, depends on how you 
> connected, if you just do;
> 
> My::Schema->connection('dbi:Foo' .. );
> 
> Then there is just one global connection, and you can call 
> search on your class names, if however you  use:
> 
> my $schema = My::Schema->compose_connection, or ->connect,
> 
> then the information about the connecion/DB is stored in the 
> $schema object (in $schema->storage), and My::Artist->search 
> will not work at all.
> 
> > Secondly, when over riding resultset methods for a specific class I 
> > believe the new methods get defined in My::Schema::Artist. But you 
> > could put them in My::Artist as well, and they would just 
> sit slightly 
> > higher up the MRO. Does anyone actually put methods in the result 
> > class file?
> 
> No, adding methods to My::Schema::Artist or My::Artist will 
> only make them available to Row objects (DBIx::Class::Row).
> 
> The difference is this:, If you run a search in scalar 
> context, what you get is a ResultSet object, which will not 
> have any of the methods you put in your individual table 
> classes (My::Artist etc.), but does have convenience methods 
> like ->count (how many items were returned) and so on. 
> Calling ->next on that result set, or calling search in list 
> context, will get you Row objects, which will each represent 
> a row of the result, and will be inherited from your 
> My::Artist/table classes, and thus inherit those methods.
> 
> So if you want to add methods to a search result as a whole, 
> you need to create your own result_class ..
> 
> I hope that makes sense,
> 
> Jess

Thanks. It makes sense, but it doesn't quite jibe with my experience.
I've made the problem more concrete...

I'm trying to override the create() method of a particular class, so
that it creates two other related objects. But using the
$schema->resultset('Foo')->create syntax bypasses my overriden method.
Is that expected?

If I define new() instead it does get called - but since I'm inserting
rows with create_related I think it needs to be in create. The method in
question looks something like:

sub create {
  my $row = shift()->next::method(@_);
  $row->create_related(..);
  $row
}



Here is a sample schema that shows create() being bypassed. Any comments
welcome.

==> ./create.pl <==
use strict;
use warnings;

use My::Setup;

my $schema = My->schema;

print "with schema->resulset\n";
$schema->resultset('Artist')->create({artistid => $$, name => 'Bill'});

print "with schema->class (resolves to class name)\n";
$schema->class('Artist')->create({artistid => $$+1, name => 'Bill'});

print "with My::Artist\n";
My::Artist->create({artistid => $$+2, name => 'Bill'});

__END__

Output is:

with schema->resulset
Found Artist new
with schema->class (resolves to class name)
Found Artist create
Found Artist new
with My::Artist
Found Artist create
Found Artist new

So the My::Schema::Artist::create() is not called when using the
resultset syntax.


==> ./db/create.sql <==
create table artist (
	artistid integer,
	name text,
	primary key( artistid )
);

==> ./lib/My/Schema/Artist.pm <==
package My::Schema::Artist;

use strict;
use warnings;

use base qw/DBIx::Class/;

__PACKAGE__->load_components( 'Core' );

__PACKAGE__->table('artist');
__PACKAGE__->add_columns(qw/artistid name/);
__PACKAGE__->primary_key('artistid');

sub new { print "Found Artist new\n"; shift()->next::method(@_);  };
sub create { print "Found Artist create\n"; shift()->next::method(@_);
};

1;

==> ./lib/My/Schema.pm <==
package My::Schema;

use strict;
use warnings;

use base qw/DBIx::Class::Schema/;

__PACKAGE__->load_classes();

1;

==> ./lib/My/Setup.pm <==
package My::Setup;

use strict;
use warnings;

use My::Schema;

my $dsn = 'dbi:SQLite:db/artist.db';

My::Schema->compose_connection( My => $dsn);

1;


Any comments welcome.

Thanks, Richard

http://www.bbc.co.uk/

This e-mail (and any attachments) is confidential and may contain
personal views which are not the views of the BBC unless specifically
stated.
If you have received it in error, please delete it from your system. 
Do not use, copy or disclose the information in any way nor act in
reliance on it and notify the sender immediately. Please note that the
BBC monitors e-mails sent or received. 
Further communication will signify your consent to this.





More information about the Dbix-class mailing list