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