53a04b0c9ad35bce22d872e5e757aff2a2628873
[dbsrgits/DBIx-Class-ParameterizedJoinHack.git] / lib / DBIx / Class / ResultSet / ParameterizedJoinHack.pm
1 package DBIx::Class::ResultSet::ParameterizedJoinHack;
2
3 use strict;
4 use warnings;
5 use DBIx::Class::ParameterizedJoinHack;
6 use base qw(DBIx::Class::ResultSet);
7
8 sub _parameterized_join_store {
9   $_[0]->result_source->result_class
10        ->$DBIx::Class::ParameterizedJoinHack::STORE
11 }
12
13 sub with_parameterized_join {
14   my ($self, $rel, $params) = @_;
15   die "Missing relation name in with_parameterized_join"
16     unless defined $rel;
17
18   {
19     my $params_ref = ref($params);
20     $params_ref = 'non-reference-value'
21       unless $params_ref;
22     die "Parameters value must be a hash ref, not ${params_ref}"
23       unless $params_ref eq 'HASH';
24   }
25
26   die "Parameterized join can only be used once per relation"
27     if exists(($self->{attrs}{join_parameters} || {})->{$rel});
28
29   $self->search_rs(
30     {},
31     { join => $rel,
32       join_parameters => {
33         %{$self->{attrs}{join_parameters}||{}},
34         $rel => $params
35       }
36     },
37   );
38 }
39
40 sub _localize_parameters {
41   my ($self, $final, $params, $store, $first, @rest) = @_;
42   return $final->() unless $first;
43   local $store->{$first}{params} = $params->{$first};
44   $self->_localize_parameters($final, $params, $store, @rest);
45 }
46
47 sub call_with_parameters {
48   my ($self, $method, @args) = @_;
49   my %params = %{$self->{attrs}{join_parameters}||{}};
50   my $store = $self->_parameterized_join_store;
51   return $self->_localize_parameters(
52     sub { $self->$method(@args) },
53     \%params, $store,
54     keys %params
55   );
56 }
57
58 sub _resolved_attrs { my $self = shift; $self->call_with_parameters($self->next::can, @_) }
59 sub related_resultset { my $self = shift; $self->call_with_parameters($self->next::can, @_) }
60
61 1;
62
63 =head1 NAME
64
65 DBIx::Class::ResultSet::ParameterizedJoinHack
66
67 =head1 SYNOPSIS
68
69     package MySchema::ResultSet::Person;
70     use base qw(DBIx::Class::ResultSet);
71
72     __PACKAGE__->load_components(qw(ResultSet::ParameterizedJoinHack));
73
74     1;
75
76 =head1 DESCRIPTION
77
78 This is a ResultSet component allowing you to access the dynamically
79 parameterized relations declared with
80 L<DBIx::Class::ParameterizedJoinHack>.
81
82 Enable the component as usual with:
83     
84     __PACKAGE__->load_components(qw( ResultSet::ParameterizedJoinHack ));
85
86 in your ResultSet class.
87
88 See L<DBIx::Class::ParameterizedJoinHack> for declaration documentation,
89 a general overview, and examples.
90
91 =head1 METHODS
92
93 =head2 with_parameterized_join
94
95     my $joined_rs = $resultset->with_parameterized_join(
96         $relation_name,
97         $parameters,
98     );
99
100 This method constructs a ResultSet joined with the given C<$relation_name>
101 by the passed C<$parameters>. The C<$relation_name> is the name as
102 declared on the Result, C<$parameters> is a hash reference with the keys
103 being the parameter names, and the values being the arguments to the join
104 builder.
105
106 =head1 SPONSORS
107
108 Development of this module was sponsored by
109
110 =over
111
112 =item * Ctrl O L<http://ctrlo.com>
113
114 =back
115
116 =head1 AUTHOR
117
118  Matt S. Trout <mst@shadowcat.co.uk>
119
120 =head1 CONTRIBUTORS
121
122 None yet.
123
124 =head1 COPYRIGHT
125
126 Copyright (c) 2015 the DBIx::Class::ParameterizedJoinHack L</AUTHOR> and L</CONTRIBUTORS>
127 as listed above.
128
129 =head1 LICENSE
130
131 This library is free software and may be distributed under the same terms
132 as perl itself.
133
134 =cut