X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FRelationship%2FBase.pm;h=0401c0ab2b60f82d308db2e87053a0e196b57bb9;hb=0b88a5bb24f2b536a11ea76e228897f60a10893d;hp=c3733e7cfa5707707a192d4ab64f11546d00bd47;hpb=880a1a0cc6a48a3165656fe5daf7ec288901c3e2;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Relationship/Base.pm b/lib/DBIx/Class/Relationship/Base.pm index c3733e7..0401c0a 100644 --- a/lib/DBIx/Class/Relationship/Base.pm +++ b/lib/DBIx/Class/Relationship/Base.pm @@ -5,7 +5,7 @@ use warnings; use base qw/DBIx::Class/; -=head1 NAME +=head1 NAME DBIx::Class::Relationship::Base - Inter-table relationships @@ -15,7 +15,7 @@ DBIx::Class::Relationship::Base - Inter-table relationships This class provides methods to describe the relationships between the tables in your database model. These are the "bare bones" relationships -methods, for predefined ones, look in L. +methods, for predefined ones, look in L. =head1 METHODS @@ -23,33 +23,48 @@ methods, for predefined ones, look in L. =over 4 -=item Arguments: ('relname', 'Foreign::Class', $cond, $attrs) +=item Arguments: 'relname', 'Foreign::Class', $cond, $attrs =back __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs); -The condition needs to be an SQL::Abstract-style representation of the -join between the tables. When resolving the condition for use in a JOIN, -keys using the pseudo-table I are resolved to mean "the Table on the -other side of the relationship", and values using the pseudo-table I +The condition needs to be an L-style representation of the +join between the tables. When resolving the condition for use in a C, +keys using the pseudo-table C are resolved to mean "the Table on the +other side of the relationship", and values using the pseudo-table C are resolved to mean "the Table this class is representing". Other restrictions, such as by value, sub-select and other tables, may also be -used. Please check your database for JOIN parameter support. +used. Please check your database for C parameter support. -For example, if you're creating a rel from Author to Book, where the Book -table has a column author_id containing the ID of the Author row: +For example, if you're creating a relationship from C to C, where +the C table has a column C containing the ID of the C +row: { 'foreign.author_id' => 'self.id' } -will result in the JOIN clause +will result in the C clause - author me JOIN book book ON bar.author_id = me.id + author me JOIN book book ON book.author_id = me.id -You can specify as many foreign => self mappings as necessary. Each key/value -pair provided in a hashref will be used as ANDed conditions, to add an ORed -condition, use an arrayref of hashrefs. See the L documentation -for more details. +For multi-column foreign keys, you will need to specify a C-to-C +mapping for each column in the key. For example, if you're creating a +relationship from C to C, where the C table refers to a +publisher and a type (e.g. "paperback"): + + { + 'foreign.publisher_id' => 'self.publisher_id', + 'foreign.type_id' => 'self.type_id', + } + +This will result in the C clause: + + book me JOIN edition edition ON edition.publisher_id = me.publisher_id + AND edition.type_id = me.type_id + +Each key-value pair provided in a hashref will be used as Ced conditions. +To add an Ced condition, use an arrayref of hashrefs. See the +L documentation for more details. Valid attributes are as follows: @@ -92,12 +107,12 @@ created, which calls C for the relationship. =over 4 -=item Arguments: ($relname, $rel_info) +=item Arguments: $relname, $rel_info =back Registers a relationship on the class. This is called internally by -L to set up Accessors and Proxies. +DBIx::Class::ResultSourceProxy to set up Accessors and Proxies. =cut @@ -107,9 +122,9 @@ sub register_relationship { } =over 4 -=item Arguments: ($relationship_name) +=item Arguments: $relationship_name -=item Returns: $related_resultset +=item Return Value: $related_resultset =back @@ -160,7 +175,8 @@ sub related_resultset { =head2 search_related - $rs->search_related('relname', $cond, $attrs); + @objects = $rs->search_related('relname', $cond, $attrs); + $objects_rs = $rs->search_related('relname', $cond, $attrs); Run a search on a related resultset. The search will be restricted to the item or items represented by the L it was called @@ -172,6 +188,19 @@ sub search_related { return shift->related_resultset(shift)->search(@_); } +=head2 search_related_rs + + ( $objects_rs ) = $rs->search_related_rs('relname', $cond, $attrs); + +This method works exactly the same as search_related, except that +it garauntees a restultset, even in list context. + +=cut + +sub search_related_rs { + return shift->related_resultset(shift)->search_rs(@_); +} + =head2 count_related $obj->count_related('relname', $cond, $attrs); @@ -238,18 +267,49 @@ sub find_related { return $self->search_related($rel)->find(@_); } +=head2 find_or_new_related + + my $new_obj = $obj->find_or_new_related('relname', \%col_data); + +Find an item of a related class. If none exists, instantiate a new item of the +related class. The object will not be saved into your storage until you call +L on it. + +=cut + +sub find_or_new_related { + my $self = shift; + return $self->find_related(@_) || $self->new_related(@_); +} + =head2 find_or_create_related my $new_obj = $obj->find_or_create_related('relname', \%col_data); Find or create an item of a related class. See -L for details. +L for details. =cut sub find_or_create_related { my $self = shift; - return $self->find_related(@_) || $self->create_related(@_); + my $obj = $self->find_related(@_); + return (defined($obj) ? $obj : $self->create_related(@_)); +} + +=head2 update_or_create_related + + my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?); + +Update or create an item of a related class. See +L for details. + +=cut + +sub update_or_create_related { + my $self = shift; + my $rel = shift; + return $self->related_resultset($rel)->update_or_create(@_); } =head2 set_from_related @@ -276,9 +336,11 @@ sub set_from_related { "condition for $rel is of type ". (ref $cond ? ref $cond : 'plain scalar') ) unless ref $cond eq 'HASH'; - my $f_class = $self->result_source->schema->class($rel_obj->{class}); - $self->throw_exception( "Object $f_obj isn't a ".$f_class ) - unless $f_obj->isa($f_class); + if (defined $f_obj) { + my $f_class = $self->result_source->schema->class($rel_obj->{class}); + $self->throw_exception( "Object $f_obj isn't a ".$f_class ) + unless $f_obj->isa($f_class); + } $self->set_columns( $self->result_source->resolve_condition( $rel_obj->{cond}, $f_obj, $rel));