1 package DBIx::Class::ParameterizedJoinHack;
5 use base qw(DBIx::Class);
7 our $VERSION = '0.002001'; # 0.2.1
8 $VERSION = eval $VERSION;
10 our $STORE = '_parameterized_join_hack_meta_info';
12 __PACKAGE__->mk_group_accessors(inherited => $STORE);
14 sub parameterized_has_many {
15 my ($class, $rel, $f_source, $cond, $attrs) = @_;
17 die "Missing relation name for parameterized_has_many"
19 die "Missing foreign source"
20 unless defined $f_source;
23 my $cond_ref = ref($cond);
24 $cond_ref = 'non-reference value'
26 die "Condition needs to be [ \\\@args, \&code ], not ${cond_ref}"
27 unless $cond_ref eq 'ARRAY';
29 my ($args, $code) = @$cond;
32 my $arg_ref = ref($cond->[0]);
33 $arg_ref = 'non-reference value'
35 die "Arguments must be declared as array ref of names, not ${arg_ref}"
36 unless $arg_ref eq 'ARRAY';
37 my $code_ref = ref($cond->[1]);
38 $code_ref = 'non-reference value'
40 die "Condition builder must be declared as code ref, not ${code_ref}"
41 unless $code_ref eq 'CODE';
44 my $store = $class->$STORE({
45 %{$class->$STORE||{}},
46 $rel => { params => {}, args => $args },
49 my $wrapped_code = sub {
50 my $params = $store->{params};
51 my @missing = grep !exists $params->{$_}, @$args;
52 die "Attempted to use parameterized rel ${rel} for ${class} without"
53 ." passing parameters ".join(', ', @missing) if @missing;
58 $class->has_many($rel, $f_source, $wrapped_code, $attrs);
59 return; # no, you are not going to accidentally rely on a return value
66 DBIx::Class::ParameterizedJoinHack - Parameterized Relationship Joins
71 # The Result class we want to allow to join with a dynamic
74 package MySchema::Result::Person;
75 use base qw(DBIx::Class::Core);
77 __PACKAGE__->load_components(qw(ParameterizedJoinHack));
78 __PACKAGE__->table('person');
79 __PACKAGE__->add_columns(
81 data_type => 'integer',
83 is_auto_increment => 1,
93 __PACKAGE__->parameterized_has_many(
94 priority_tasks => 'MySchema::Result::Task',
95 [['min_priority'] => sub {
98 "$args->{foreign_alias}.owner_id" => {
99 -ident => "$args->{self_alias}.id",
101 "$args->{foreign_alias}.priority" => {
102 '>=' => $_{min_priority},
111 # The ResultSet class belonging to your Result
113 package MySchema::ResultSet::Person;
114 use base qw(DBIx::Class::ResultSet);
116 __PACKAGE__->load_components(qw(ResultSet::ParameterizedJoinHack));
121 # A Result class to join against.
123 package MySchema::Result::Task;
124 use base qw(DBIx::Class::Core);
126 __PACKAGE__->table('task');
127 __PACKAGE__->add_columns(
129 data_type => 'integer',
131 is_auto_increment => 1,
134 data_type => 'integer',
138 data_type => 'integer',
148 # Using the parameterized join.
150 my @urgent = MySchema
152 ->resultset('Person')
153 ->with_parameterized_join(
162 This module uses L<DBIx::Class> internals and may break at any time.
166 This L<DBIx::Class> component allows to declare dynamically parameterized
167 has-many relationships.
169 Add the component to your Result class as usual:
171 __PACKAGE__->load_components(qw( ParameterizedJoinHack ));
173 See L</parameterized_has_many> for details on declaring relations.
175 See L<DBIx::Class::ResultSet::ParameterizedJoinHack> for ResultSet usage.
177 B<Note:> Currently only L</parameterized_has_many> is implemented, since
178 it is the most requested use-case. However, adding support for other
179 relationship types is possible if a use-case is found.
183 =head2 parameterized_has_many
185 __PACKAGE__->parameterized_has_many(
188 [\@join_arg_names, \&join_builder],
192 The C<$relation_name>, C<$foreign_source>, and C<$attrs> are passed
193 through to C<has_many> as usual. The third argument is an array reference
194 containing an (array reference) list of argument names and a code
195 reference used to build the join conditions.
197 The code reference will be called with the same arguments as if it had
198 been passed to C<has_many> directly, but the global C<%_> hash will
199 contain the named arguments for the join.
201 See the L</SYNOPSIS> for an example of a definition.
205 Development of this module was sponsored by
209 =item * Ctrl O L<http://ctrlo.com>
215 Matt S. Trout <mst@shadowcat.co.uk>
219 Robert Sedlacek <r.sedlacek@shadowcat.co.uk>
223 Copyright (c) 2015 the DBIx::Class::ParameterizedJoinHack L</AUTHOR> and L</CONTRIBUTORS>
228 This library is free software and may be distributed under the same terms