1 package DBIx::Class::ParameterizedJoinHack;
5 use base qw(DBIx::Class);
7 our $VERSION = '0.000001'; # 0.0.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 my $cond_ref = ref($cond);
18 die "Condition needs to be [ \\\@args, \$code ], not ${cond_ref}"
19 unless $cond_ref eq 'ARRAY';
21 my ($args, $code) = @$cond;
22 my $store = $class->$STORE({
23 %{$class->$STORE||{}},
24 $rel => { params => {}, args => $args },
26 my $wrapped_code = sub {
27 my $params = $store->{$rel}{params};
28 my @missing = grep !exists $params->{$_}, @$args;
29 die "Attempted to use parameterized rel ${rel} for ${class} without"
30 ." passing parameters ".join(', ', @missing) if @missing;
34 $class->has_many($rel, $f_source, $wrapped_code, $attrs);
35 return; # no, you are not going to accidentally rely on a return value
42 DBIx::Class::ParameterizedJoinHack - Parameterized Relationship Joins
47 # The Result class we want to allow to join with a dynamic
50 package MySchema::Result::Person;
51 use base qw(DBIx::Class::Core);
53 __PACKAGE__->load_components(qw(ParameterizedJoinHack));
54 __PACKAGE__->table('person');
55 __PACKAGE__->add_columns(
57 data_type => 'integer',
59 is_auto_increment => 1,
69 __PACKAGE__->parameterized_has_many(
70 priority_tasks => 'MySchema::Result::Task',
71 [['min_priority'] => sub {
74 "$args->{foreign_alias}.owner_id" => {
75 -ident => "$args->{self_alias}.id",
77 "$args->{foreign_alias}.priority" => {
78 '>=' => $_{min_priority},
87 # The ResultSet class belonging to your Result
89 package MySchema::ResultSet::Person;
90 use base qw(DBIx::Class::ResultSet);
92 __PACKAGE__->load_components(qw(ResultSet::ParameterizedJoinHack));
97 # A Result class to join against.
99 package MySchema::Result::Task;
100 use base qw(DBIx::Class::Core);
102 __PACKAGE__->table('task');
103 __PACKAGE__->add_columns(
105 data_type => 'integer',
107 is_auto_increment => 1,
110 data_type => 'integer',
114 data_type => 'integer',
124 # Using the parameterized join.
126 my @urgent = MySchema
128 ->resultset('Person')
129 ->with_parameterized_join(
138 This L<DBIx::Class> component allows to declare dynamically parameterized
139 has-many relationships.
141 Add the component to your Result class as usual:
143 __PACKAGE__->load_components(qw( ParameterizedJoinHack ));
145 See L<parameterized_has_many> for details on declaring relations.
147 See L<DBIx::Class::ResultSet::ParameterizedJoinHack> for ResultSet usage.
151 =head2 parameterized_has_many
153 __PACKAGE__->parameterized_has_many(
156 [\@join_arg_names, \&join_builder],
160 The C<$relation_name>, C<$foreign_source>, and C<$attrs> are passed
161 through to C<has_many> as usual. The third argument is an array reference
162 containing an (array reference) list of argument names and a code
163 reference used to build the join conditions.
165 The code reference will be called with the same arguments as if it had
166 been passed to C<has_many> directly, but the global C<%_> hash will
167 contain the named arguments for the join.
169 See the L</SYNOPSIS> for an example of a definition.
173 Development of this module was sponsored by
177 =item * Ctrl O L<http://ctrlo.com>
183 Matt S. Trout <mst@shadowcat.co.uk>
191 Copyright (c) 2015 the DBIx::Class::ParameterizedJoinHack L</AUTHOR> and L</CONTRIBUTORS>
196 This library is free software and may be distributed under the same terms