File Coverage

blib/lib/Rose/DB/Object/Metadata/Relationship/ManyToOne.pm
Criterion Covered Total %
statement 65 94 69.1
branch 24 48 50.0
condition 11 26 42.3
subroutine 17 23 73.9
pod 7 14 50.0
total 124 205 60.4


line stmt bran cond sub pod time code
1             package Rose::DB::Object::Metadata::Relationship::ManyToOne;
2              
3 61     61   495 use strict;
  61         162  
  61         1867  
4              
5 61     61   355 use Carp();
  61         142  
  61         846  
6 61     61   325 use Scalar::Util();
  61         151  
  61         1102  
7              
8 61     61   32023 use Rose::DB::Object::Metadata::Relationship;
  61         214  
  61         3528  
9             our @ISA = qw(Rose::DB::Object::Metadata::Relationship);
10              
11 61     61   547 use Rose::Object::MakeMethods::Generic;
  61         202  
  61         328  
12 61     61   1872 use Rose::DB::Object::MakeMethods::Generic;
  61         167  
  61         510  
13              
14             our $VERSION = '0.781';
15              
16             __PACKAGE__->default_auto_method_types(qw(get_set_on_save delete_on_save));
17              
18             __PACKAGE__->add_common_method_maker_argument_names
19             (
20             qw(class share_db key_columns required manager_class manager_method
21             manager_count_method manager_iterator_method manager_find_method
22             manager_delete_method manager_args query_args join_args object_args)
23             );
24              
25             use Rose::Object::MakeMethods::Generic
26             (
27 61         638 boolean =>
28             [
29             #'required' => { default => 1 },
30             '_share_db' => { default => 1 },
31             'with_column_triggers' => { default => 0 },
32             'disable_column_triggers',
33             ],
34              
35             hash =>
36             [
37             _key_column => { hash_key => 'key_columns' },
38             _key_columns => { interface => 'get_set_all' },
39             ],
40 61     61   6494 );
  61         157  
41              
42             Rose::Object::MakeMethods::Generic->make_methods
43             (
44             { preserve_existing => 1 },
45             scalar =>
46             [
47             __PACKAGE__->common_method_maker_argument_names
48             ],
49             );
50              
51             __PACKAGE__->method_maker_info
52             (
53             get_set =>
54             {
55             class => 'Rose::DB::Object::MakeMethods::Generic',
56             type => 'object_by_key',
57             },
58              
59             get_set_now =>
60             {
61             class => 'Rose::DB::Object::MakeMethods::Generic',
62             type => 'object_by_key',
63             interface => 'get_set_now',
64             },
65              
66             get_set_on_save =>
67             {
68             class => 'Rose::DB::Object::MakeMethods::Generic',
69             type => 'object_by_key',
70             interface => 'get_set_on_save',
71             },
72              
73             delete_now =>
74             {
75             class => 'Rose::DB::Object::MakeMethods::Generic',
76             type => 'object_by_key',
77             interface => 'delete_now',
78             },
79              
80             delete_on_save =>
81             {
82             class => 'Rose::DB::Object::MakeMethods::Generic',
83             type => 'object_by_key',
84             interface => 'delete_on_save',
85             },
86             );
87              
88 76     76 1 273 sub type { 'many to one' }
89              
90 0     0 1 0 sub is_singular { 1 }
91              
92 0     0 0 0 sub foreign_class { shift->class(@_) }
93              
94 32     32 0 64 sub share_db { shift->_fk_or_self(share_db => @_) }
95 0     0 0 0 sub key_column { shift->_fk_or_self(key_column => @_) }
96 322     322 0 15128 sub key_columns { shift->_fk_or_self(key_columns => @_) }
97              
98             *map_column = \&key_column;
99             *column_map = \&key_columns;
100              
101             sub _fk_or_self
102             {
103 354     354   613 my($self, $method) = (shift, shift);
104              
105 354 100 66     1275 if((@_ && $method eq 'key_columns') ||
      33        
      66        
106             (@_ > 1 && $method eq 'key_column'))
107             {
108 8         28 $self->{'default_required'} = undef;
109             }
110              
111 354 100       987 if(my $fk = $self->foreign_key)
112             {
113 250         1123 return $fk->$method(@_);
114             }
115              
116 104 50       414 $method = "_$method" if($self->can("_$method"));
117 104         282 return $self->$method(@_);
118             }
119              
120             sub method_name
121             {
122 176     176 1 287 my($self) = shift;
123              
124 176 100       475 if(my $fk = $self->foreign_key)
125             {
126 128         526 return $fk->method_name(@_);
127             }
128              
129 48         120 return $self->SUPER::method_name(@_);
130             }
131              
132             sub is_ready_to_make_methods
133             {
134 40     40 0 78 my($self) = shift;
135              
136 40 100       142 if(my $fk = $self->foreign_key)
137             {
138 32         155 return $fk->is_ready_to_make_methods(@_);
139             }
140              
141 8         53 return $self->SUPER::is_ready_to_make_methods(@_);
142             }
143              
144             sub make_methods
145             {
146 28     28 1 72 my($self) = shift;
147              
148 28 100       95 if(my $fk = $self->foreign_key)
149             {
150 20         107 return $fk->make_methods(@_);
151             }
152              
153 8         40 $self->SUPER::make_methods(@_);
154              
155 8 50       33 if($self->with_column_triggers)
156             {
157 0   0     0 my $method = $self->method_name('get_set_on_save') ||
158             $self->method_name('get_set');
159              
160 0 0       0 if($method)
161             {
162 0 0       0 my $meta = $self->parent or
163             Carp::croak "Missing parent for relationship '", $self->name, "'";
164              
165 0         0 my $column_map = $self->column_map;
166              
167 0         0 foreach my $column_name (keys %$column_map)
168             {
169 0         0 my $column = $meta->column($column_name);
170 0         0 my $accessor = $column->accessor_method_name;
171              
172 0         0 my $trigger_name = 'clear_rel_' . $self->name;
173              
174 0 0       0 unless(defined $column->builtin_trigger_index('on_set', $trigger_name))
175             {
176 0         0 my $wolumn = Scalar::Util::weaken($column);
177              
178             $column->add_builtin_trigger(
179             event => 'on_set',
180             name => $trigger_name,
181             code => sub
182             {
183 0     0   0 my($obj) = shift;
184 0 0       0 return if($self->{'disable_column_triggers'});
185 0         0 local $wolumn->{'triggers_disabled'} = 1;
186 0 0       0 $obj->$method(undef) unless(defined $obj->$accessor());
187 0         0 });
188             }
189             }
190             }
191             }
192             }
193              
194             sub id
195             {
196 266     266 0 414 my($self) = shift;
197              
198 266         846 my $column_map = $self->column_map;
199              
200             return $self->parent->class . ' ' . $self->class . ' ' .
201 266         886 join("\0", map { join("\1", lc $_, lc $column_map->{$_}) } sort keys %$column_map) .
202 266   100     1720 join("\0", map { $_ . '=' . ($self->$_() || 0) } qw(required));
  266         736  
203             }
204              
205             sub build_method_name_for_type
206             {
207 16     16 1 51 my($self, $type) = @_;
208              
209 16 100 33     105 if($type eq 'get_set' || $type eq 'get_set_now' || $type eq 'get_set_on_save')
    50 66        
      33        
210             {
211 8         32 return $self->name;
212             }
213             elsif($type eq 'delete_now' || $type eq 'delete_on_save')
214             {
215 8         52 return 'delete_' . $self->name;
216             }
217              
218 0         0 return undef;
219             }
220              
221             sub optional
222             {
223 0     0 1 0 my($self) = shift;
224              
225 0 0       0 if(@_)
226             {
227 0         0 $self->required(!$_[0]);
228             }
229              
230 0         0 return ! $self->required;
231             }
232              
233             *soft = \&optional;
234              
235             sub required
236             {
237 298     298 1 479 my($self) = shift;
238              
239 298         505 my $fk = $self->foreign_key;
240 298 100       614 return $fk->referential_integrity(@_) if($fk);
241              
242 48 0       109 return $self->{'required'} = ($_[0] ? 1 : 0) if(@_);
    50          
243 48 50       103 return $self->{'required'} if(defined $self->{'required'});
244 48 100       153 return $self->{'default_required'} if(defined $self->{'default_required'});
245              
246 8 50       23 my $meta = $self->parent or
247             Carp::croak "Missing parent for foreign key '", $self->name, "'";
248              
249 8         23 my $column_map = $self->column_map;
250              
251             # If any local key column allows null values, then
252             # the related object is not required.
253 8         56 foreach my $column_name (keys %$column_map)
254             {
255 8 50       27 my $column = $meta->column($column_name)
256             or Carp::confess "No such column '$column_name' in table '",
257             $self->parent->table, "' referenced from relationship '",
258             $self->name, "'";
259              
260 8 50       30 unless($column->not_null)
261             {
262 8         96 return $self->{'default_required'} = 0;
263             }
264             }
265              
266             # If the local key columns are the same as the primary key columns
267             # then the related object is not required.
268 0           my $local_columns = join("\0", sort keys %$column_map);
269 0           my $pk_columns = join("\0", sort $meta->primary_key_column_names);
270              
271 0 0 0       if($local_columns eq $pk_columns && length($local_columns))
272             {
273 0           return $self->{'default_required'} = 0;
274             }
275              
276 0           return $self->{'default_required'} = 1;
277             }
278              
279             *referential_integrity = \&required;
280              
281 0     0 0   sub requires_preexisting_parent_object { 0 }
282              
283             1;
284              
285             __END__
286              
287             =head1 NAME
288              
289             Rose::DB::Object::Metadata::Relationship::ManyToOne - Many to one table relationship metadata object.
290              
291             =head1 SYNOPSIS
292              
293             use Rose::DB::Object::Metadata::Relationship::ManyToOne;
294              
295             $rel = Rose::DB::Object::Metadata::Relationship::ManyToOne->new(...);
296             $rel->make_methods(...);
297             ...
298              
299             =head1 DESCRIPTION
300              
301             Objects of this class store and manipulate metadata for relationships in which a many rows in one table may refer to a single row in another table.
302              
303             This class inherits from L<Rose::DB::Object::Metadata::Relationship>. Inherited methods that are not overridden will not be documented a second time here. See the L<Rose::DB::Object::Metadata::Relationship> documentation for more information.
304              
305             =head1 METHOD MAP
306              
307             =over 4
308              
309             =item C<get_set>
310              
311             L<Rose::DB::Object::MakeMethods::Generic>, L<object_by_key|Rose::DB::Object::MakeMethods::Generic/object_by_key>, ...
312              
313             =item C<get_set_now>
314              
315             L<Rose::DB::Object::MakeMethods::Generic>, L<object_by_key|Rose::DB::Object::MakeMethods::Generic/object_by_key>, C<interface =E<gt> 'get_set_now'>
316              
317             =item C<get_set_on_save>
318              
319             L<Rose::DB::Object::MakeMethods::Generic>, L<object_by_key|Rose::DB::Object::MakeMethods::Generic/object_by_key>, C<interface =E<gt> 'get_set_on_save'>
320              
321             =item C<delete_now>
322              
323             L<Rose::DB::Object::MakeMethods::Generic>, L<object_by_key|Rose::DB::Object::MakeMethods::Generic/object_by_key>, C<interface =E<gt> 'delete_now'>
324              
325             =item C<delete_on_save>
326              
327             L<Rose::DB::Object::MakeMethods::Generic>, L<object_by_key|Rose::DB::Object::MakeMethods::Generic/object_by_key>, C<interface =E<gt> 'delete_on_save'>
328              
329             =back
330              
331             See the L<Rose::DB::Object::Metadata::Relationship|Rose::DB::Object::Metadata::Relationship/"MAKING METHODS"> documentation for an explanation of this method map.
332              
333             =head1 CLASS METHODS
334              
335             =over 4
336              
337             =item B<default_auto_method_types [TYPES]>
338              
339             Get or set the default list of L<auto_method_types|Rose::DB::Object::Metadata::Relationship/auto_method_types>. TYPES should be a list of relationship method types. Returns the list of default relationship method types (in list context) or a reference to an array of the default relationship method types (in scalar context). The default list contains "get_set_on_save" and "delete_on_save".
340              
341             =back
342              
343             =head1 OBJECT METHODS
344              
345             =over 4
346              
347             =item B<column_map [HASH | HASHREF]>
348              
349             Get or set a reference to a hash that maps local column names to foreign column names.
350              
351             =item B<build_method_name_for_type TYPE>
352              
353             Return a method name for the relationship method type TYPE.
354              
355             For the method types "get_set", "get_set_now", and "get_set_on_save", the relationship's L<name|Rose::DB::Object::Metadata::Relationship/name> is returned.
356              
357             For the method types "delete_now" and "delete_on_save", the relationship's L<name|Rose::DB::Object::Metadata::Relationship/name> prefixed with "delete_" is returned.
358              
359             Otherwise, undef is returned.
360              
361             =item B<foreign_key [FK]>
362              
363             Get or set the L<Rose::DB::Object::Metadata::ForeignKey> object to which this object delegates all responsibility.
364              
365             Many to one relationships encapsulate essentially the same information as foreign keys. If a foreign key object is stored in this relationship object, then I<all compatible operations are passed through to the foreign key object.> This includes making object method(s) and adding or modifying the local-to-foreign column map. In other words, if a L<foreign_key|/foreign_key> is set, the relationship object simply acts as a proxy for the foreign key object.
366              
367             =item B<is_singular>
368              
369             Returns true.
370              
371             =item B<manager_class [CLASS]>
372              
373             Get or set the name of the L<Rose::DB::Object::Manager>-derived class used to fetch the object.
374              
375             =item B<manager_method [METHOD]>
376              
377             Get or set the name of the L<manager_class|/manager_class> class method to call when fetching the object.
378              
379             =item B<manager_count_method [METHOD]>
380              
381             Get or set the name of the L<manager_class|/manager_class> class method to call when counting objects. The L<make_methods|Rose::DB::Object::Metadata::Relationship/make_methods> method will use L<get_objects_count|Rose::DB::Object::Manager/get_objects_count> if this value is left undefined.
382              
383             =item B<manager_iterator_method [METHOD]>
384              
385             Get or set the name of the L<manager_class|/manager_class> class method to call when creating an iterator. The L<make_methods|Rose::DB::Object::Metadata::Relationship/make_methods> method will use L<get_objects_iterator|Rose::DB::Object::Manager/get_objects_iterator> if this value is left undefined.
386              
387             =item B<manager_delete_method [METHOD]>
388              
389             Get or set the name of the L<manager_class|/manager_class> class method to call when deleting objects. The L<make_methods|Rose::DB::Object::Metadata::Relationship/make_methods> method will use L<delete_objects|Rose::DB::Object::Manager/delete_objects> if this value is left undefined.
390              
391             =item B<manager_args [HASHREF]>
392              
393             Get or set a reference to a hash of name/value arguments to pass to the L<manager_method|/manager_method> when fetching the object. See the documentation for L<Rose::DB::Object::Manager>'s L<get_objects|Rose::DB::Object::Manager/get_objects> method for a full list of valid arguments for use with the C<manager_args> parameter.
394              
395             B<Note:> when the name of a relationship that has C<manager_args> is used in a L<Rose::DB::Object::Manager> L<with_objects|Rose::DB::Object::Manager/with_objects> or L<require_objects|Rose::DB::Object::Manager/require_objects> parameter value, I<only> the L<sort_by|Rose::DB::Object::Manager/sort_by> argument will be copied from C<manager_args> and incorporated into the query.
396              
397             =item B<map_column LOCAL [, FOREIGN]>
398              
399             If passed a local column name LOCAL, return the corresponding column name in the foreign table. If passed both a local column name LOCAL and a foreign column name FOREIGN, set the local/foreign mapping and return the foreign column name.
400              
401             =item B<object_args [HASHREF]>
402              
403             Get or set a reference to a hash of name/value pairs to pass to the L<new|Rose::DB::Object/new> method when constructing the related object. This attribute conflicts with any use of the C<manager_*> or C<query_args> attributes.
404              
405             =item B<optional [BOOL]>
406              
407             This method is the mirror image of the L<required|/required> method. Passing a true value to this method is the same thing as setting L<required|/required> to false, and vice versa. Similarly, the return value is the logical negation of L<required|/required>.
408              
409             =item B<query_args [ARRAYREF]>
410              
411             Get or set a reference to an array of query arguments to add to the L<query|Rose::DB::Object::Manager/query> passed to the L<manager_method|/manager_method> when fetching the object.
412              
413             =item B<required [BOOL]>
414              
415             Get or set the boolean value that determines what happens when the local columns in the L<column_map|/column_map> have L<defined|perlfunc/defined> values, but the object they relate to is not found. If true, a fatal error will occur when the methods that fetch objects through this relationship are called. If false, then the methods will simply return undef.
416              
417             The default is false if one or more of the local columns L<allow null values|Rose::DB::Object::Metadata::Column/not_null> or if the local columns in the column map are the same as the L<primary key columns|Rose::DB::Object::Metadata/primary_key_columns>, true otherwise.
418              
419             =item B<type>
420              
421             Returns "many to one".
422              
423             =item B<with_column_triggers [BOOL]>
424              
425             Get or set a boolean value that indicates whether or not L<triggers|Rose::DB::Object::Metadata::Column/TRIGGERS> should be added to the local columns in the L<column map|/column_map> in an attempt to keep related objects and local columns in sync. Defaults to false.
426              
427             =back
428              
429             =head1 AUTHOR
430              
431             John C. Siracusa (siracusa@gmail.com)
432              
433             =head1 LICENSE
434              
435             Copyright (c) 2010 by John C. Siracusa. All rights reserved. This program is
436             free software; you can redistribute it and/or modify it under the same terms
437             as Perl itself.