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