File Coverage

blib/lib/Fey/Meta/Role/Relationship/HasMany.pm
Criterion Covered Total %
statement 49 54 90.7
branch 5 6 83.3
condition n/a
subroutine 14 17 82.3
pod 2 2 100.0
total 70 79 88.6


line stmt bran cond sub pod time code
1             package Fey::Meta::Role::Relationship::HasMany;
2              
3 10     10   7214 use strict;
  10         14  
  10         331  
4 10     10   49 use warnings;
  10         18  
  10         307  
5 10     10   47 use namespace::autoclean;
  10         18  
  10         71  
6              
7             our $VERSION = '0.47';
8              
9 10     10   909 use Fey::Exceptions qw( param_error );
  10         15  
  10         769  
10 10     10   4864 use Fey::Object::Iterator::FromSelect;
  10         44  
  10         520  
11 10     10   7232 use Fey::Object::Iterator::FromSelect::Caching;
  10         44  
  10         569  
12 10     10   96 use Fey::ORM::Types qw( ClassDoesIterator );
  10         16  
  10         80  
13              
14 10     10   21420 use Moose::Role;
  10         21  
  10         102  
15              
16             with 'Fey::Meta::Role::Relationship';
17              
18             has associated_method => (
19             is => 'rw',
20             isa => 'Moose::Meta::Method',
21             init_arg => undef,
22             lazy => 1,
23             builder => '_build_associated_method',
24             );
25              
26             has 'iterator_class' => (
27             is => 'ro',
28             isa => ClassDoesIterator,
29             lazy => 1,
30             builder => '_build_iterator_class',
31             );
32              
33             sub _build_iterator_class {
34 7     7   15 my $self = shift;
35              
36 7 100       304 return $self->is_cached()
37             ? 'Fey::Object::Iterator::FromSelect::Caching'
38             : 'Fey::Object::Iterator::FromSelect';
39             }
40              
41 7     7   298 sub _build_is_cached {0}
42              
43             sub _build_associated_method {
44 9     9   26 my $self = shift;
45              
46 9         15 my $method;
47 9 100       389 if ( $self->is_cached() ) {
48 2         85 my $iter_attr_name = q{___} . $self->name() . q{_iterator};
49              
50 2         94 $self->associated_class()->add_attribute(
51             $iter_attr_name,
52             is => 'ro',
53             isa => $self->iterator_class(),
54             lazy => 1,
55             default => $self->_make_iterator_maker(),
56             init_arg => undef,
57             );
58              
59 2     0   9468 $method = sub { return $_[0]->$iter_attr_name()->clone() };
  0     0   0  
60             }
61             else {
62 7         48 $method = $self->_make_iterator_maker();
63             }
64              
65 7         329 return $self->associated_class()->method_metaclass()->wrap(
66             name => $self->name(),
67             package_name => $self->associated_class()->name(),
68             body => $method,
69             );
70             }
71              
72             ## no critic (Subroutines::ProhibitUnusedPrivateSubroutines)
73             sub _make_subref_for_sql {
74 7     7   14 my $self = shift;
75 7         18 my $select = shift;
76 7         11 my $bind_sub = shift;
77              
78 7         344 my $target_table = $self->foreign_table();
79              
80 7         302 my $iterator_class = $self->iterator_class();
81              
82             return sub {
83 0     0   0 my $self = shift;
84              
85 0         0 my $class = $self->meta()->ClassForTable($target_table);
86              
87 0         0 my $dbh = $self->_dbh($select);
88              
89 0         0 return $iterator_class->new(
90             classes => $class,
91             dbh => $dbh,
92             select => $select,
93             bind_params => [ $self->$bind_sub() ],
94             );
95 7         84 };
96              
97             }
98             ## use critic
99              
100             sub attach_to_class {
101 9     9 1 24 my $self = shift;
102 9         22 my $class = shift;
103              
104 9         512 $self->_set_associated_class($class);
105              
106 9         398 $class->add_method( $self->name() => $self->associated_method() );
107             }
108              
109             sub detach_from_class {
110 4     4 1 10 my $self = shift;
111              
112 4 50       176 return unless $self->associated_class();
113              
114 4         223 $self->associated_class->remove_method( $self->name() );
115              
116 4         454 $self->_clear_associated_class();
117             }
118              
119             1;
120              
121             # ABSTRACT: A role for has-many metaclasses
122              
123             __END__
124              
125             =pod
126              
127             =head1 NAME
128              
129             Fey::Meta::Role::Relationship::HasMany - A role for has-many metaclasses
130              
131             =head1 VERSION
132              
133             version 0.47
134              
135             =head1 DESCRIPTION
136              
137             This role provides shared functionality for the two has-many metaclasses,
138             L<Fey::Meta::HasMany::ViaFK> and L<Fey::Meta::HasMany::ViaSelect>.
139              
140             =head1 CONSTRUCTOR OPTIONS
141              
142             This role adds the following constructor options:
143              
144             =over 4
145              
146             =item * is_cached
147              
148             Defaults to false for this class.
149              
150             =item * iterator_class
151              
152             This is the class used for iterators over the objects in this
153             relationship. By default, if this relationship is cached, it uses
154             L<Fey::Object::Iterator::FromSelect::Caching>, otherwise it uses
155             L<Fey::Object::Iterator::FromSelect>
156              
157             =back
158              
159             =head1 METHODS
160              
161             This role provides the following methods:
162              
163             =head2 $hm->name()
164              
165             Corresponds to the value passed to the constructor.
166              
167             =head2 $hm->table()
168              
169             Corresponds to the value passed to the constructor.
170              
171             =head2 $hm->foreign_table()
172              
173             Corresponds to the value passed to the constructor.
174              
175             =head2 $ho->is_cached()
176              
177             Corresponds to the value passed to the constructor, or the calculated
178             default.
179              
180             =head2 $hm->iterator_class()
181              
182             Corresponds to the value passed to the constructor, or the calculated
183             default.
184              
185             =head2 $hm->attach_to_class($class)
186              
187             This method takes a F<Fey::Meta::Class::Table> object and attaches the
188             relationship to the associated class. Doing so will create a new
189             method in the associated class.
190              
191             =head2 $hm->associated_class()
192              
193             The class associated with this object. This is undefined until C<<
194             $hm->attach_to_class() >> is called.
195              
196             =head2 $hm->associated_method()
197              
198             Returns the method associated with this object, if any.
199              
200             =head2 $hm->detach_from_class()
201              
202             If this object was attached to a class, it removes the method it made,
203             and unsets the C<associated_class>.
204              
205             =head1 AUTHOR
206              
207             Dave Rolsky <autarch@urth.org>
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             This software is copyright (c) 2011 - 2015 by Dave Rolsky.
212              
213             This is free software; you can redistribute it and/or modify it under
214             the same terms as the Perl 5 programming language system itself.
215              
216             =cut