POD::Coverage additions
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Relationship / Base.pm
CommitLineData
55e2d745 1package DBIx::Class::Relationship::Base;
2
3use strict;
4use warnings;
5
1edd1722 6use base qw/DBIx::Class/;
55e2d745 7
75d07914 8=head1 NAME
55e2d745 9
8918977e 10DBIx::Class::Relationship::Base - Inter-table relationships
55e2d745 11
12=head1 SYNOPSIS
13
14=head1 DESCRIPTION
15
30236e47 16This class provides methods to describe the relationships between the
17tables in your database model. These are the "bare bones" relationships
75d07914 18methods, for predefined ones, look in L<DBIx::Class::Relationship>.
55e2d745 19
20=head1 METHODS
21
8091aa91 22=head2 add_relationship
503536d5 23
27f01d1f 24=over 4
25
ebc77b53 26=item Arguments: 'relname', 'Foreign::Class', $cond, $attrs
27f01d1f 27
28=back
30236e47 29
503536d5 30 __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs);
31
5271499d 32The condition needs to be an L<SQL::Abstract>-style representation of the
33join between the tables. When resolving the condition for use in a C<JOIN>,
34keys using the pseudo-table C<foreign> are resolved to mean "the Table on the
35other side of the relationship", and values using the pseudo-table C<self>
30236e47 36are resolved to mean "the Table this class is representing". Other
37restrictions, such as by value, sub-select and other tables, may also be
5271499d 38used. Please check your database for C<JOIN> parameter support.
30236e47 39
5271499d 40For example, if you're creating a relationship from C<Author> to C<Book>, where
41the C<Book> table has a column C<author_id> containing the ID of the C<Author>
42row:
503536d5 43
30236e47 44 { 'foreign.author_id' => 'self.id' }
503536d5 45
5271499d 46will result in the C<JOIN> clause
503536d5 47
5271499d 48 author me JOIN book book ON book.author_id = me.id
503536d5 49
5271499d 50For multi-column foreign keys, you will need to specify a C<foreign>-to-C<self>
51mapping for each column in the key. For example, if you're creating a
52relationship from C<Book> to C<Edition>, where the C<Edition> table refers to a
53publisher and a type (e.g. "paperback"):
54
55 {
781102cd 56 'foreign.publisher_id' => 'self.publisher_id',
5271499d 57 'foreign.type_id' => 'self.type_id',
58 }
59
60This will result in the C<JOIN> clause:
61
62 book me JOIN edition edition ON edition.publisher_id = me.publisher_id
63 AND edition.type_id = me.type_id
64
65Each key-value pair provided in a hashref will be used as C<AND>ed conditions.
66To add an C<OR>ed condition, use an arrayref of hashrefs. See the
67L<SQL::Abstract> documentation for more details.
8091aa91 68
69Valid attributes are as follows:
70
71=over 4
72
73=item join_type
74
75Explicitly specifies the type of join to use in the relationship. Any SQL
76join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
77command immediately before C<JOIN>.
78
79=item proxy
80
30236e47 81An arrayref containing a list of accessors in the foreign class to create in
8091aa91 82the main class. If, for example, you do the following:
83
27f01d1f 84 MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
85 undef, {
86 proxy => [ qw/notes/ ],
87 });
8091aa91 88
30236e47 89Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
8091aa91 90
30236e47 91 my $cd = MyDB::Schema::CD->find(1);
92 $cd->notes('Notes go here'); # set notes -- LinerNotes object is
93 # created if it doesn't exist
8091aa91 94
95=item accessor
96
97Specifies the type of accessor that should be created for the relationship.
98Valid values are C<single> (for when there is only a single related object),
99C<multi> (when there can be many), and C<filter> (for when there is a single
100related object, but you also want the relationship accessor to double as
101a column accessor). For C<multi> accessors, an add_to_* method is also
102created, which calls C<create_related> for the relationship.
103
104=back
105
87c4e602 106=head2 register_relationship
107
27f01d1f 108=over 4
109
ebc77b53 110=item Arguments: $relname, $rel_info
27f01d1f 111
112=back
71e65b39 113
30236e47 114Registers a relationship on the class. This is called internally by
71f9df37 115DBIx::Class::ResultSourceProxy to set up Accessors and Proxies.
71e65b39 116
55e2d745 117=cut
118
71e65b39 119sub register_relationship { }
120
27f01d1f 121=head2 related_resultset
122
123=over 4
124
ebc77b53 125=item Arguments: $relationship_name
27f01d1f 126
d601dc88 127=item Return Value: $related_resultset
27f01d1f 128
129=back
30236e47 130
27f01d1f 131 $rs = $cd->related_resultset('artist');
30236e47 132
27f01d1f 133Returns a L<DBIx::Class::ResultSet> for the relationship named
134$relationship_name.
30236e47 135
136=cut
137
138sub related_resultset {
139 my $self = shift;
bc0c9800 140 $self->throw_exception("Can't call *_related as class methods")
141 unless ref $self;
30236e47 142 my $rel = shift;
143 my $rel_obj = $self->relationship_info($rel);
bc0c9800 144 $self->throw_exception( "No such relationship ${rel}" )
145 unless $rel_obj;
30236e47 146
147 return $self->{related_resultsets}{$rel} ||= do {
148 my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
149 $attrs = { %{$rel_obj->{attrs} || {}}, %$attrs };
150
bc0c9800 151 $self->throw_exception( "Invalid query: @_" )
152 if (@_ > 1 && (@_ % 2 == 1));
30236e47 153 my $query = ((@_ > 1) ? {@_} : shift);
154
bc0c9800 155 my $cond = $self->result_source->resolve_condition(
156 $rel_obj->{cond}, $rel, $self
157 );
30236e47 158 if (ref $cond eq 'ARRAY') {
159 $cond = [ map { my $hash;
160 foreach my $key (keys %$_) {
161 my $newkey = $key =~ /\./ ? "me.$key" : $key;
162 $hash->{$newkey} = $_->{$key};
163 }; $hash } @$cond ];
164 } else {
165 foreach my $key (grep { ! /\./ } keys %$cond) {
166 $cond->{"me.$key"} = delete $cond->{$key};
167 }
168 }
169 $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
bc0c9800 170 $self->result_source->related_source($rel)->resultset->search(
171 $query, $attrs
172 );
30236e47 173 };
174}
175
8091aa91 176=head2 search_related
503536d5 177
5b89a768 178 @objects = $rs->search_related('relname', $cond, $attrs);
179 $objects_rs = $rs->search_related('relname', $cond, $attrs);
30236e47 180
181Run a search on a related resultset. The search will be restricted to the
182item or items represented by the L<DBIx::Class::ResultSet> it was called
183upon. This method can be called on a ResultSet, a Row or a ResultSource class.
503536d5 184
185=cut
186
55e2d745 187sub search_related {
ff7bb7a1 188 return shift->related_resultset(shift)->search(@_);
b52e9bf8 189}
190
5b89a768 191=head2 search_related_rs
192
193 ( $objects_rs ) = $rs->search_related_rs('relname', $cond, $attrs);
194
60a8fb95 195This method works exactly the same as search_related, except that
196it garauntees a restultset, even in list context.
5b89a768 197
198=cut
199
200sub search_related_rs {
201 return shift->related_resultset(shift)->search_rs(@_);
202}
203
b52e9bf8 204=head2 count_related
205
7be93b07 206 $obj->count_related('relname', $cond, $attrs);
b52e9bf8 207
bc0c9800 208Returns the count of all the items in the related resultset, restricted by the
209current item or where conditions. Can be called on a
27f01d1f 210L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
bc0c9800 211L<DBIx::Class::Manual::Glossary/"Row"> object.
30236e47 212
b52e9bf8 213=cut
214
215sub count_related {
216 my $self = shift;
217 return $self->search_related(@_)->count;
55e2d745 218}
219
30236e47 220=head2 new_related
221
222 my $new_obj = $obj->new_related('relname', \%col_data);
223
224Create a new item of the related foreign class. If called on a
27f01d1f 225L<DBIx::Class::Manual::Glossary/"Row"> object, it will magically set any
226primary key values into foreign key columns for you. The newly created item
227will not be saved into your storage until you call L<DBIx::Class::Row/insert>
30236e47 228on it.
229
230=cut
231
232sub new_related {
233 my ($self, $rel, $values, $attrs) = @_;
234 return $self->search_related($rel)->new($values, $attrs);
235}
236
8091aa91 237=head2 create_related
503536d5 238
30236e47 239 my $new_obj = $obj->create_related('relname', \%col_data);
240
241Creates a new item, similarly to new_related, and also inserts the item's data
242into your storage medium. See the distinction between C<create> and C<new>
243in L<DBIx::Class::ResultSet> for details.
503536d5 244
245=cut
246
55e2d745 247sub create_related {
3842b955 248 my $self = shift;
fea3d045 249 my $rel = shift;
64acc2bc 250 my $obj = $self->search_related($rel)->create(@_);
251 delete $self->{related_resultsets}->{$rel};
252 return $obj;
55e2d745 253}
254
8091aa91 255=head2 find_related
503536d5 256
30236e47 257 my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
258
259Attempt to find a related object using its primary key or unique constraints.
27f01d1f 260See L<DBIx::Class::ResultSet/find> for details.
503536d5 261
262=cut
263
1a14aa3f 264sub find_related {
265 my $self = shift;
266 my $rel = shift;
716b3d29 267 return $self->search_related($rel)->find(@_);
1a14aa3f 268}
269
b3e1f1f5 270=head2 find_or_new_related
271
272 my $new_obj = $obj->find_or_new_related('relname', \%col_data);
273
274Find an item of a related class. If none exists, instantiate a new item of the
275related class. The object will not be saved into your storage until you call
276L<DBIx::Class::Row/insert> on it.
277
278=cut
279
280sub find_or_new_related {
281 my $self = shift;
282 return $self->find_related(@_) || $self->new_related(@_);
283}
284
8091aa91 285=head2 find_or_create_related
503536d5 286
30236e47 287 my $new_obj = $obj->find_or_create_related('relname', \%col_data);
288
27f01d1f 289Find or create an item of a related class. See
b3e1f1f5 290L<DBIx::Class::ResultSet/find_or_create> for details.
503536d5 291
292=cut
293
55e2d745 294sub find_or_create_related {
295 my $self = shift;
9c2c91ea 296 my $obj = $self->find_related(@_);
297 return (defined($obj) ? $obj : $self->create_related(@_));
55e2d745 298}
299
045120e6 300=head2 update_or_create_related
301
302 my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?);
303
304Update or create an item of a related class. See
f7e1846f 305L<DBIx::Class::ResultSet/update_or_create> for details.
045120e6 306
307=cut
308
309sub update_or_create_related {
310 my $self = shift;
311 my $rel = shift;
312 return $self->related_resultset($rel)->update_or_create(@_);
313}
314
8091aa91 315=head2 set_from_related
503536d5 316
30236e47 317 $book->set_from_related('author', $author_obj);
318
319Set column values on the current object, using related values from the given
320related object. This is used to associate previously separate objects, for
321example, to set the correct author for a book, find the Author object, then
322call set_from_related on the book.
323
27f01d1f 324The columns are only set in the local copy of the object, call L</update> to
325set them in the storage.
503536d5 326
327=cut
328
55e2d745 329sub set_from_related {
330 my ($self, $rel, $f_obj) = @_;
4685e006 331 my $rel_obj = $self->relationship_info($rel);
701da8c4 332 $self->throw_exception( "No such relationship ${rel}" ) unless $rel_obj;
55e2d745 333 my $cond = $rel_obj->{cond};
bc0c9800 334 $self->throw_exception(
335 "set_from_related can only handle a hash condition; the ".
336 "condition for $rel is of type ".
337 (ref $cond ? ref $cond : 'plain scalar')
338 ) unless ref $cond eq 'HASH';
2c037e6b 339 if (defined $f_obj) {
340 my $f_class = $self->result_source->schema->class($rel_obj->{class});
341 $self->throw_exception( "Object $f_obj isn't a ".$f_class )
342 unless $f_obj->isa($f_class);
343 }
fde6e28e 344 $self->set_columns(
345 $self->result_source->resolve_condition(
346 $rel_obj->{cond}, $f_obj, $rel));
55e2d745 347 return 1;
348}
349
8091aa91 350=head2 update_from_related
503536d5 351
30236e47 352 $book->update_from_related('author', $author_obj);
353
27f01d1f 354The same as L</"set_from_related">, but the changes are immediately updated
355in storage.
503536d5 356
357=cut
358
55e2d745 359sub update_from_related {
360 my $self = shift;
361 $self->set_from_related(@_);
362 $self->update;
363}
364
8091aa91 365=head2 delete_related
503536d5 366
30236e47 367 $obj->delete_related('relname', $cond, $attrs);
368
369Delete any related item subject to the given conditions.
503536d5 370
371=cut
372
55e2d745 373sub delete_related {
374 my $self = shift;
64acc2bc 375 my $obj = $self->search_related(@_)->delete;
376 delete $self->{related_resultsets}->{$_[0]};
377 return $obj;
55e2d745 378}
379
3801;
381
55e2d745 382=head1 AUTHORS
383
daec44b8 384Matt S. Trout <mst@shadowcatsystems.co.uk>
55e2d745 385
386=head1 LICENSE
387
388You may distribute this code under the same terms as Perl itself.
389
390=cut
391