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