44496c435f249aa711f6c510ce7c97353e6531c0
[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 base qw/DBIx::Class/;
7
8 use Scalar::Util qw/weaken blessed/;
9 use Try::Tiny;
10 use namespace::clean;
11
12 =head1 NAME
13
14 DBIx::Class::Relationship::Base - Inter-table relationships
15
16 =head1 SYNOPSIS
17
18     __PACKAGE__->add_relationship('spiders',
19                                   'My::DB::Result::Creatures',
20                                   sub {
21                                     my ( $me_alias, $rel_alias) = @_;
22                                     return
23                                        { "${rel_alias}.id"    => { '=' => \"${me_alias}.id"},
24                                          "${rel_alias}.type"  => { '=', "arachnid" },
25                                         };
26                                      
27                                   });
28
29 =head1 DESCRIPTION
30
31 This class provides methods to describe the relationships between the
32 tables in your database model. These are the "bare bones" relationships
33 methods, for predefined ones, look in L<DBIx::Class::Relationship>.
34
35 =head1 METHODS
36
37 =head2 add_relationship
38
39 =over 4
40
41 =item Arguments: 'relname', 'Foreign::Class', $condition, $attrs
42
43 =back
44
45   __PACKAGE__->add_relationship('relname', 
46                                 'Foreign::Class', 
47                                 $condition, $attrs);
48
49 Create a custom relationship between one result source and another
50 source, indicated by its class name.
51
52 =head3 condition
53
54 The condition argument describes the JOIN expression used to connect
55 the two sources when creating SQL queries.
56
57 To create simple equality joins, supply a hashref containing the
58 remote table column name as the key(s), and the local table column
59 name as the value(s), for example:
60
61   { 'foreign.author_id' => 'self.id' }
62
63 will result in the C<JOIN> clause:
64
65   author me JOIN book book ON book.author_id = me.id
66
67 This describes a relationship between the C<Author> table and the
68 C<Book> table where the C<Book> table has a column C<author_id>
69 containing the ID value of the C<Author>.
70
71 C<foreign> and C<self> are psuedo aliases and must be entered
72 literally. They will be replaced with the actual correct table alias
73 when the SQL is produced.
74
75 Similarly:
76
77   {
78     'foreign.publisher_id' => 'self.publisher_id',
79     'foreign.type_id'      => 'self.type_id',
80   }
81
82 will result in the C<JOIN> clause:
83
84   book me JOIN edition edition ON edition.publisher_id = me.publisher_id
85     AND edition.type_id = me.type_id
86
87 This describes the relationship from C<Book> to C<Edition>, where the
88 C<Edition> table refers to a publisher and a type (e.g. "paperback"):
89
90 As is the default in L<SQL::Abstract>, the key-value pairs will be
91 C<AND>ed in the result. C<OR> can be achieved with an arrayref, for
92 example:
93
94   [
95     { 'foreign.left_itemid' => 'self.id' },
96     { 'foreign.right_itemid' => 'self.id' },
97   ]
98
99 which results in the C<JOIN> clause:
100
101   items me JOIN related_items rel_link ON rel_link.left_itemid = me.id
102     OR rel_link.right_itemid = me.id
103
104 This describes the relationship from C<Items> to C<RelatedItems>,
105 where C<RelatedItems> is a many-to-many linking table, linking Items
106 back to themselves.
107
108 To create joins which describe more than a simple equality of column
109 values, the custom join condition coderef syntax can be used:
110
111     sub {
112       my ( $me_alias, $rel_alias ) = @_;
113       return
114         ({ "${rel_alias}.artist"  => { '=' => \"${me_alias}.artistid"},
115            "${rel_alias}.year"    => { '>', "1979",
116                                        '<', "1990" }
117          });
118   }
119
120 this will result in the C<JOIN> clause:
121
122   artist me LEFT JOIN cd cds_80s_noopt ON 
123    ( cds_80s_noopt.artist = me.artistid 
124      AND ( cds_80s_noopt.year < ? AND cds_80s_noopt.year > ? )
125    )
126
127 with the bind values:
128
129    '1990', '1979'
130
131 C<$rel_alias> is the equivalent to C<foreign> in the simple syntax,
132 and will be replaced by the actual remote table alias in the produced
133 SQL. Similarly, C<$me_alias> is the equivalent to C<self> and will be
134 replaced with the local table alias in the SQL.
135
136 The actual syntax returned by the coderef should be valid
137 L<SQL::Abstract> syntax, similar to normal
138 L<DBIx::Class::ResultSet/search> conditions.
139
140 To help optimise the SQL produced, a second optional hashref can be
141 returned to be used when the relationship accessor is called directly
142 on a Row object:
143
144     sub {
145       my ( $me_alias, $rel_alias, $me_result_source, 
146            $rel_name, $optional_me_object ) = @_;
147       return
148         ({ "${rel_alias}.artist"  => { '=' => \"${me_alias}.artistid"},
149            "${rel_alias}.year"    => { '>', "1979",
150                                        '<', "1990" }
151          },
152          $optional_me_object &&
153          { "${rel_alias}.artist" => $optional_me_object->artistid,
154            "${rel_alias}.year"   => { '>', "1979",
155                                       '<', "1990" }
156        });
157   }
158
159 Now this code:
160
161     my $artist = $schema->resultset("Artist")->find({ id => 4 });
162     $artist->cds_80s->all;
163
164 Produces:
165
166     SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
167       FROM cd me 
168       WHERE ( ( me.artist = ? AND ( me.year < ? AND me.year > ? ) ) )
169
170 With the bind values:
171
172     '4', '1990', '1979'
173
174 The C<$optional_me_object> used to create the second hashref contains
175 a row object, the object that the relation accessor was called on.
176
177 C<$me_result_source> the L<DBIx::Class::ResultSource> of the table
178 being searched on, and C<$rel_name>, the name of the relation
179 containing this condition, are also provided as arguments. These may
180 be useful to more complicated condition calculation.
181
182 =head3 attributes
183
184 The L<standard ResultSet attributes|DBIx::Class::ResultSet/ATTRIBUTES> may
185 be used as relationship attributes. In particular, the 'where' attribute is
186 useful for filtering relationships:
187
188      __PACKAGE__->has_many( 'valid_users', 'MyApp::Schema::User',
189         { 'foreign.user_id' => 'self.user_id' },
190         { where => { valid => 1 } }
191     );
192
193 The following attributes are also valid:
194
195 =over 4
196
197 =item join_type
198
199 Explicitly specifies the type of join to use in the relationship. Any SQL
200 join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in the SQL
201 command immediately before C<JOIN>.
202
203 =item proxy =E<gt> $column | \@columns | \%column
204
205 =over 4
206
207 =item \@columns
208
209 An arrayref containing a list of accessors in the foreign class to create in
210 the main class. If, for example, you do the following:
211
212   MyDB::Schema::CD->might_have(liner_notes => 'MyDB::Schema::LinerNotes',
213     undef, {
214       proxy => [ qw/notes/ ],
215     });
216
217 Then, assuming MyDB::Schema::LinerNotes has an accessor named notes, you can do:
218
219   my $cd = MyDB::Schema::CD->find(1);
220   $cd->notes('Notes go here'); # set notes -- LinerNotes object is
221                                # created if it doesn't exist
222
223 =item \%column
224
225 A hashref where each key is the accessor you want installed in the main class,
226 and its value is the name of the original in the fireign class.
227
228   MyDB::Schema::Track->belongs_to( cd => 'DBICTest::Schema::CD', 'cd', {
229       proxy => { cd_title => 'title' },
230   });
231
232 This will create an accessor named C<cd_title> on the C<$track> row object.
233
234 =back
235
236 NOTE: you can pass a nested struct too, for example:
237
238   MyDB::Schema::Track->belongs_to( cd => 'DBICTest::Schema::CD', 'cd', {
239     proxy => [ 'year', { cd_title => 'title' } ],
240   });
241
242 =item accessor
243
244 Specifies the type of accessor that should be created for the relationship.
245 Valid values are C<single> (for when there is only a single related object),
246 C<multi> (when there can be many), and C<filter> (for when there is a single
247 related object, but you also want the relationship accessor to double as
248 a column accessor). For C<multi> accessors, an add_to_* method is also
249 created, which calls C<create_related> for the relationship.
250
251 =item is_foreign_key_constraint
252
253 If you are using L<SQL::Translator> to create SQL for you and you find that it
254 is creating constraints where it shouldn't, or not creating them where it
255 should, set this attribute to a true or false value to override the detection
256 of when to create constraints.
257
258 =item cascade_copy
259
260 If C<cascade_copy> is true on a C<has_many> relationship for an
261 object, then when you copy the object all the related objects will
262 be copied too. To turn this behaviour off, pass C<< cascade_copy => 0 >>
263 in the C<$attr> hashref.
264
265 The behaviour defaults to C<< cascade_copy => 1 >> for C<has_many>
266 relationships.
267
268 =item cascade_delete
269
270 By default, DBIx::Class cascades deletes across C<has_many>,
271 C<has_one> and C<might_have> relationships. You can disable this
272 behaviour on a per-relationship basis by supplying
273 C<< cascade_delete => 0 >> in the relationship attributes.
274
275 The cascaded operations are performed after the requested delete,
276 so if your database has a constraint on the relationship, it will
277 have deleted/updated the related records or raised an exception
278 before DBIx::Class gets to perform the cascaded operation.
279
280 =item cascade_update
281
282 By default, DBIx::Class cascades updates across C<has_one> and
283 C<might_have> relationships. You can disable this behaviour on a
284 per-relationship basis by supplying C<< cascade_update => 0 >> in
285 the relationship attributes.
286
287 This is not a RDMS style cascade update - it purely means that when
288 an object has update called on it, all the related objects also
289 have update called. It will not change foreign keys automatically -
290 you must arrange to do this yourself.
291
292 =item on_delete / on_update
293
294 If you are using L<SQL::Translator> to create SQL for you, you can use these
295 attributes to explicitly set the desired C<ON DELETE> or C<ON UPDATE> constraint
296 type. If not supplied the SQLT parser will attempt to infer the constraint type by
297 interrogating the attributes of the B<opposite> relationship. For any 'multi'
298 relationship with C<< cascade_delete => 1 >>, the corresponding belongs_to
299 relationship will be created with an C<ON DELETE CASCADE> constraint. For any
300 relationship bearing C<< cascade_copy => 1 >> the resulting belongs_to constraint
301 will be C<ON UPDATE CASCADE>. If you wish to disable this autodetection, and just
302 use the RDBMS' default constraint type, pass C<< on_delete => undef >> or
303 C<< on_delete => '' >>, and the same for C<on_update> respectively.
304
305 =item is_deferrable
306
307 Tells L<SQL::Translator> that the foreign key constraint it creates should be
308 deferrable. In other words, the user may request that the constraint be ignored
309 until the end of the transaction. Currently, only the PostgreSQL producer
310 actually supports this.
311
312 =item add_fk_index
313
314 Tells L<SQL::Translator> to add an index for this constraint. Can also be
315 specified globally in the args to L<DBIx::Class::Schema/deploy> or
316 L<DBIx::Class::Schema/create_ddl_dir>. Default is on, set to 0 to disable.
317
318 =back
319
320 =head2 register_relationship
321
322 =over 4
323
324 =item Arguments: $relname, $rel_info
325
326 =back
327
328 Registers a relationship on the class. This is called internally by
329 DBIx::Class::ResultSourceProxy to set up Accessors and Proxies.
330
331 =cut
332
333 sub register_relationship { }
334
335 =head2 related_resultset
336
337 =over 4
338
339 =item Arguments: $relationship_name
340
341 =item Return Value: $related_resultset
342
343 =back
344
345   $rs = $cd->related_resultset('artist');
346
347 Returns a L<DBIx::Class::ResultSet> for the relationship named
348 $relationship_name.
349
350 =cut
351
352 sub related_resultset {
353   my $self = shift;
354   $self->throw_exception("Can't call *_related as class methods")
355     unless ref $self;
356   my $rel = shift;
357   my $rel_info = $self->relationship_info($rel);
358   $self->throw_exception( "No such relationship ${rel}" )
359     unless $rel_info;
360
361   return $self->{related_resultsets}{$rel} ||= do {
362     my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
363     $attrs = { %{$rel_info->{attrs} || {}}, %$attrs };
364
365     $self->throw_exception( "Invalid query: @_" )
366       if (@_ > 1 && (@_ % 2 == 1));
367     my $query = ((@_ > 1) ? {@_} : shift);
368
369     my $source = $self->result_source;
370
371     # condition resolution may fail if an incomplete master-object prefetch
372     # is encountered - that is ok during prefetch construction (not yet in_storage)
373
374     # if $rel_info->{cond} is a CODE, we might need to join from the
375     # current resultsource instead of just querying the target
376     # resultsource, in that case, the condition might provide an
377     # additional condition in order to avoid an unecessary join if
378     # that is at all possible.
379     my ($cond, $extended_cond) = try {
380       $source->_resolve_condition( $rel_info->{cond}, $rel, $self )
381     }
382     catch {
383       if ($self->in_storage) {
384         $self->throw_exception ($_);
385       }
386
387       $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION;  # RV
388     };
389
390     if ($cond eq $DBIx::Class::ResultSource::UNRESOLVABLE_CONDITION) {
391       my $reverse = $source->reverse_relationship_info($rel);
392       foreach my $rev_rel (keys %$reverse) {
393         if ($reverse->{$rev_rel}{attrs}{accessor} && $reverse->{$rev_rel}{attrs}{accessor} eq 'multi') {
394           $attrs->{related_objects}{$rev_rel} = [ $self ];
395           weaken $attrs->{related_object}{$rev_rel}[0];
396         } else {
397           $attrs->{related_objects}{$rev_rel} = $self;
398           weaken $attrs->{related_object}{$rev_rel};
399         }
400       }
401     }
402
403     # this is where we're going to check if we have an extended
404     # rel. In that case, we need to: 1) If there's a second
405     # condition, we use that instead.  2) If there is only one
406     # condition, we need to join the current resultsource and have
407     # additional conditions.
408     if (ref $rel_info->{cond} eq 'CODE') {
409       # this is an extended relationship.
410       if ($extended_cond) {
411         $cond = $extended_cond;
412
413       } else {
414
415         # it's a bit hard to find out what to do with other joins
416         $self->throw_exception('Extended relationship '.$rel.' with additional join requires optimized declaration')
417           if exists $attrs->{join} && $attrs->{join};
418
419         # aliases get a bit more complicated, so we won't accept additional queries
420         $self->throw_exception('Extended relationship '.$rel.' with additional query requires optimized declaration')
421           if $query;
422
423         $attrs->{from} =
424           [ { $rel => $self->result_source->from },
425             [ { 'me' => $self->result_source->related_source($rel)->from }, { 1 => 1 } ] ];
426
427         $cond->{"${rel}.${_}"} = $self->get_column($_) for $self->result_source->primary_columns;
428       }
429     }
430
431     if (ref $cond eq 'ARRAY') {
432       $cond = [ map {
433         if (ref $_ eq 'HASH') {
434           my $hash;
435           foreach my $key (keys %$_) {
436             my $newkey = $key !~ /\./ ? "me.$key" : $key;
437             $hash->{$newkey} = $_->{$key};
438           }
439           $hash;
440         } else {
441           $_;
442         }
443       } @$cond ];
444     } elsif (ref $cond eq 'HASH') {
445       foreach my $key (grep { ! /\./ } keys %$cond) {
446         $cond->{"me.$key"} = delete $cond->{$key};
447       }
448     }
449
450     $query = ($query ? { '-and' => [ $cond, $query ] } : $cond);
451     $self->result_source->related_source($rel)->resultset->search(
452       $query, $attrs
453     );
454   };
455 }
456
457 =head2 search_related
458
459   @objects = $rs->search_related('relname', $cond, $attrs);
460   $objects_rs = $rs->search_related('relname', $cond, $attrs);
461
462 Run a search on a related resultset. The search will be restricted to the
463 item or items represented by the L<DBIx::Class::ResultSet> it was called
464 upon. This method can be called on a ResultSet, a Row or a ResultSource class.
465
466 =cut
467
468 sub search_related {
469   return shift->related_resultset(shift)->search(@_);
470 }
471
472 =head2 search_related_rs
473
474   ( $objects_rs ) = $rs->search_related_rs('relname', $cond, $attrs);
475
476 This method works exactly the same as search_related, except that
477 it guarantees a resultset, even in list context.
478
479 =cut
480
481 sub search_related_rs {
482   return shift->related_resultset(shift)->search_rs(@_);
483 }
484
485 =head2 count_related
486
487   $obj->count_related('relname', $cond, $attrs);
488
489 Returns the count of all the items in the related resultset, restricted by the
490 current item or where conditions. Can be called on a
491 L<DBIx::Class::Manual::Glossary/"ResultSet"> or a
492 L<DBIx::Class::Manual::Glossary/"Row"> object.
493
494 =cut
495
496 sub count_related {
497   my $self = shift;
498   return $self->search_related(@_)->count;
499 }
500
501 =head2 new_related
502
503   my $new_obj = $obj->new_related('relname', \%col_data);
504
505 Create a new item of the related foreign class. If called on a
506 L<Row|DBIx::Class::Manual::Glossary/"Row"> object, it will magically
507 set any foreign key columns of the new object to the related primary
508 key columns of the source object for you.  The newly created item will
509 not be saved into your storage until you call L<DBIx::Class::Row/insert>
510 on it.
511
512 =cut
513
514 sub new_related {
515   my ($self, $rel, $values, $attrs) = @_;
516   return $self->search_related($rel)->new($values, $attrs);
517 }
518
519 =head2 create_related
520
521   my $new_obj = $obj->create_related('relname', \%col_data);
522
523 Creates a new item, similarly to new_related, and also inserts the item's data
524 into your storage medium. See the distinction between C<create> and C<new>
525 in L<DBIx::Class::ResultSet> for details.
526
527 =cut
528
529 sub create_related {
530   my $self = shift;
531   my $rel = shift;
532   my $obj = $self->search_related($rel)->create(@_);
533   delete $self->{related_resultsets}->{$rel};
534   return $obj;
535 }
536
537 =head2 find_related
538
539   my $found_item = $obj->find_related('relname', @pri_vals | \%pri_vals);
540
541 Attempt to find a related object using its primary key or unique constraints.
542 See L<DBIx::Class::ResultSet/find> for details.
543
544 =cut
545
546 sub find_related {
547   my $self = shift;
548   my $rel = shift;
549   return $self->search_related($rel)->find(@_);
550 }
551
552 =head2 find_or_new_related
553
554   my $new_obj = $obj->find_or_new_related('relname', \%col_data);
555
556 Find an item of a related class. If none exists, instantiate a new item of the
557 related class. The object will not be saved into your storage until you call
558 L<DBIx::Class::Row/insert> on it.
559
560 =cut
561
562 sub find_or_new_related {
563   my $self = shift;
564   my $obj = $self->find_related(@_);
565   return defined $obj ? $obj : $self->new_related(@_);
566 }
567
568 =head2 find_or_create_related
569
570   my $new_obj = $obj->find_or_create_related('relname', \%col_data);
571
572 Find or create an item of a related class. See
573 L<DBIx::Class::ResultSet/find_or_create> for details.
574
575 =cut
576
577 sub find_or_create_related {
578   my $self = shift;
579   my $obj = $self->find_related(@_);
580   return (defined($obj) ? $obj : $self->create_related(@_));
581 }
582
583 =head2 update_or_create_related
584
585   my $updated_item = $obj->update_or_create_related('relname', \%col_data, \%attrs?);
586
587 Update or create an item of a related class. See
588 L<DBIx::Class::ResultSet/update_or_create> for details.
589
590 =cut
591
592 sub update_or_create_related {
593   my $self = shift;
594   my $rel = shift;
595   return $self->related_resultset($rel)->update_or_create(@_);
596 }
597
598 =head2 set_from_related
599
600   $book->set_from_related('author', $author_obj);
601   $book->author($author_obj);                      ## same thing
602
603 Set column values on the current object, using related values from the given
604 related object. This is used to associate previously separate objects, for
605 example, to set the correct author for a book, find the Author object, then
606 call set_from_related on the book.
607
608 This is called internally when you pass existing objects as values to
609 L<DBIx::Class::ResultSet/create>, or pass an object to a belongs_to accessor.
610
611 The columns are only set in the local copy of the object, call L</update> to
612 set them in the storage.
613
614 =cut
615
616 sub set_from_related {
617   my ($self, $rel, $f_obj) = @_;
618   my $rel_info = $self->relationship_info($rel);
619   $self->throw_exception( "No such relationship ${rel}" ) unless $rel_info;
620   my $cond = $rel_info->{cond};
621   $self->throw_exception(
622     "set_from_related can only handle a hash condition; the ".
623     "condition for $rel is of type ".
624     (ref $cond ? ref $cond : 'plain scalar')
625   ) unless ref $cond eq 'HASH';
626   if (defined $f_obj) {
627     my $f_class = $rel_info->{class};
628     $self->throw_exception( "Object $f_obj isn't a ".$f_class )
629       unless blessed $f_obj and $f_obj->isa($f_class);
630   }
631
632   # _resolve_condition might return two hashrefs, specially in the
633   # current case, since we know $f_object is an object.
634   my ($condref1, $condref2) = $self->result_source->_resolve_condition
635     ($rel_info->{cond}, $f_obj, $rel);
636
637   # if we get two condrefs, we need to use the second, otherwise we
638   # use the first.
639   $self->set_columns($condref2 ? $condref2 : $condref1);
640
641   return 1;
642 }
643
644 =head2 update_from_related
645
646   $book->update_from_related('author', $author_obj);
647
648 The same as L</"set_from_related">, but the changes are immediately updated
649 in storage.
650
651 =cut
652
653 sub update_from_related {
654   my $self = shift;
655   $self->set_from_related(@_);
656   $self->update;
657 }
658
659 =head2 delete_related
660
661   $obj->delete_related('relname', $cond, $attrs);
662
663 Delete any related item subject to the given conditions.
664
665 =cut
666
667 sub delete_related {
668   my $self = shift;
669   my $obj = $self->search_related(@_)->delete;
670   delete $self->{related_resultsets}->{$_[0]};
671   return $obj;
672 }
673
674 =head2 add_to_$rel
675
676 B<Currently only available for C<has_many>, C<many-to-many> and 'multi' type
677 relationships.>
678
679 =over 4
680
681 =item Arguments: ($foreign_vals | $obj), $link_vals?
682
683 =back
684
685   my $role = $schema->resultset('Role')->find(1);
686   $actor->add_to_roles($role);
687       # creates a My::DBIC::Schema::ActorRoles linking table row object
688
689   $actor->add_to_roles({ name => 'lead' }, { salary => 15_000_000 });
690       # creates a new My::DBIC::Schema::Role row object and the linking table
691       # object with an extra column in the link
692
693 Adds a linking table object for C<$obj> or C<$foreign_vals>. If the first
694 argument is a hash reference, the related object is created first with the
695 column values in the hash. If an object reference is given, just the linking
696 table object is created. In either case, any additional column values for the
697 linking table object can be specified in C<$link_vals>.
698
699 =head2 set_$rel
700
701 B<Currently only available for C<many-to-many> relationships.>
702
703 =over 4
704
705 =item Arguments: (\@hashrefs | \@objs), $link_vals?
706
707 =back
708
709   my $actor = $schema->resultset('Actor')->find(1);
710   my @roles = $schema->resultset('Role')->search({ role =>
711      { '-in' => ['Fred', 'Barney'] } } );
712
713   $actor->set_roles(\@roles);
714      # Replaces all of $actor's previous roles with the two named
715
716   $actor->set_roles(\@roles, { salary => 15_000_000 });
717      # Sets a column in the link table for all roles
718
719
720 Replace all the related objects with the given reference to a list of
721 objects. This does a C<delete> B<on the link table resultset> to remove the
722 association between the current object and all related objects, then calls
723 C<add_to_$rel> repeatedly to link all the new objects.
724
725 Note that this means that this method will B<not> delete any objects in the
726 table on the right side of the relation, merely that it will delete the link
727 between them.
728
729 Due to a mistake in the original implementation of this method, it will also
730 accept a list of objects or hash references. This is B<deprecated> and will be
731 removed in a future version.
732
733 =head2 remove_from_$rel
734
735 B<Currently only available for C<many-to-many> relationships.>
736
737 =over 4
738
739 =item Arguments: $obj
740
741 =back
742
743   my $role = $schema->resultset('Role')->find(1);
744   $actor->remove_from_roles($role);
745       # removes $role's My::DBIC::Schema::ActorRoles linking table row object
746
747 Removes the link between the current object and the related object. Note that
748 the related object itself won't be deleted unless you call ->delete() on
749 it. This method just removes the link between the two objects.
750
751 =head1 AUTHORS
752
753 Matt S. Trout <mst@shadowcatsystems.co.uk>
754
755 =head1 LICENSE
756
757 You may distribute this code under the same terms as Perl itself.
758
759 =cut
760
761 1;