X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FManual%2FCookbook.pod;h=4f9fe63682a0cd9994651d86cba2d81a96525e94;hb=87980de749bd86e74b71f708237b9910790a9b87;hp=8fd5e0ac6aafb6b5eb60b36b04783226167fb130;hpb=ee38fa40d848a164040097286b4440d4b64565e8;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index 8fd5e0a..4f9fe63 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -1,68 +1,113 @@ -=head1 DBIx::Class Cookbook +=head1 NAME -=over 4 +DBIx::Class::Manual::Cookbook - Misc recipes -=item Input validation. +=head1 DESCRIPTION -=item Using joins +Things that could be handy -=item Many-to-many relationships +=head1 RECIPES -This is not as easy as it could be, but it's possible. Here's an example to -illustrate: - - package Base; - - use base qw/DBIx::Class/; - - __PACKAGE__->load_components(qw/Core DB/); - __PACKAGE__->connection(...); +=head2 Disconnecting cleanly - package Left; +If you find yourself quitting an app with Control-C a lot during development, +you might like to put the following signal handler in your main database +class to make sure it disconnects cleanly: - use base qw/Base/; + $SIG{INT} = sub { + __PACKAGE__->storage->dbh->disconnect; + }; - __PACKAGE__->table('left'); - __PACKAGE__->add_columns(qw/id left_stuff/); - __PACKAGE__->set_primary_key(qw/id/); - __PACKAGE__->has_many('mid' => 'Mid'); +=head2 Using joins and prefetch - sub right { - my ($self) = @_; - return Right->search( - { 'left.id' => $self->id }, - { join => { 'mid' => 'left' }}); - } +See L. - package Mid; +=head2 Transactions - use base qw/Base/; +As of version 0.04001, there is improved transaction support in +L. Here is an example of the recommended way to use it: - __PACKAGE__->table('mid'); - __PACKAGE__->add_columns(qw/left right/); - __PACKAGE__->set_primary_key(qw/left right/); + my $obj = Genus->find(12); + eval { + MyDB->tx_begin; + $obj->add_to_species({ name => 'troglodyte' }); + $obj->wings(2); + $obj->update; + cromulate($obj); # can have a nested transation + MyDB->tx_commit; + }; + if ($@) { eval { MyDB->tx_rollback } } # rollback might fail, too - __PACKAGE__->belongs_to('left' => 'Left'); - __PACKAGE__->belongs_to('right' => 'Right'); +Currently, a nested commit will do nothing and a nested rollback will die. +The code at each level must be sure to call rollback in the case of an error, +to ensure that the rollback will propagate to the top level and be issued. +Support for savepoints and for true nested transactions (for databases that +support them) will hopefully be added in the future. - package Right; +=head2 Many-to-many relationships - use base qw/Base/; - - __PACKAGE__->table('right'); - __PACKAGE__->add_columns(qw/id right_stuff/); - __PACKAGE__->set_primary_key(qw/id/); - __PACKAGE__->has_many('mid' => 'Mid'); - - sub left { - my ($self) = @_; - return Left->search( - { 'right.id' => $self->id }, - { join => { 'mid' => 'right' }); - } - -=item Advanced Exception handling +This is not as easy as it could be, but it's possible. Here's an example to +illustrate: -=item Transactions + # Set up inherited connection information + package MyApp::DBIC; + use base qw/DBIx::Class/; + + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/); + __PACKAGE__->connection(...); + + # Set up a class for the 'authors' table + package MyApp::DBIC::Author; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('authors'); + __PACKAGE__->add_columns(qw/authID first_name last_name/); + __PACKAGE__->set_primary_key(qw/authID/); + + # Define relationship to the link table + __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'authID'); + + # Create the accessor for books from the ::Author class + sub books { + my ($self) = @_; + return MyApp::DBIC::Book->search( + { 'b2a.authID' => $self->authID }, # WHERE clause + { join => 'b2a' } # join condition (part of search attrs) + # 'b2a' refers to the relationship named earlier in the Author class. + # 'b2a.authID' refers to the authID column of the b2a relationship, + # which becomes accessible in the search by being joined. + ); + } + + # define the link table class + package MyApp::DBIC::Book2Author; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('book2author'); + __PACKAGE__->add_columns(qw/bookID authID/); + __PACKAGE__->set_primary_key(qw/bookID authID/); + + __PACKAGE__->belongs_to('authID' => 'MyApp::DBIC::Author'); + __PACKAGE__->belongs_to('bookID' => 'MyApp::DBIC::Book'); + + package MyApp::DBIC::Book; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('books'); + __PACKAGE__->add_columns(qw/bookID title edition isbn publisher year/); + __PACKAGE__->set_primary_key(qw/bookID/); + + __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'bookID'); + + sub authors { + my ($self) = @_; + return MyApp::DBIC::Author->search( + { 'b2a.bookID' => $self->bookID }, # WHERE clause + { join => 'b2a' }); # join condition (part of search attrs) + } + + # So the above search returns an author record where the bookID field of the + # book2author table equals the bookID of the books (using the bookID + # relationship table =back