my $store = $class->$STORE({
%{$class->$STORE||{}},
$rel => { params => {}, args => $args },
- });
+ })->{$rel};
my $wrapped_code = sub {
- my $params = $store->{$rel}{params};
+ my $params = $store->{params};
my @missing = grep !exists $params->{$_}, @$args;
die "Attempted to use parameterized rel ${rel} for ${class} without"
." passing parameters ".join(', ', @missing) if @missing;
);
}
+sub _localize_parameters {
+ my ($self, $final, $params, $store, $first, @rest) = @_;
+ return $final->() unless $first;
+ local $store->{$first}{params} = $params->{$first};
+ $self->_localize_parameters($final, $params, $store, @rest);
+}
+
sub call_with_parameters {
my ($self, $method, @args) = @_;
my %params = %{$self->{attrs}{join_parameters}||{}};
my $store = $self->_parameterized_join_store;
- local @{$store}{keys %params} = map {
- +{ %{$store->{$_}}, params => $params{$_} }
- } keys %params;
- return $self->$method(@args);
+ return $self->_localize_parameters(
+ sub { $self->$method(@args) },
+ \%params, $store,
+ keys %params
+ );
}
sub _resolved_attrs { my $self = shift; $self->call_with_parameters($self->next::can, @_) }
use strict;
use warnings;
use lib 't/lib';
-use Test::More qw(no_plan);
+use Test::More;
use My::Schema;
my $schema = My::Schema->connect('dbi:SQLite:dbname=:memory:');
urgency => 30,
});
-my $test_rs = $schema
- ->resultset('Person')
- ->search({ 'me.name' => { -like => 'Bob%' } });
+subtest 'has_many' => sub {
-is $test_rs->with_parameterized_join(
- urgent_assigned_tasks => { urgency_threshold => 20 },
-)->count, 1, 'joined';
+ my $join_with_min = sub {
+ return shift->with_parameterized_join(
+ urgent_assigned_tasks => { urgency_threshold => $_[0] },
+ );
+ };
-is $test_rs->with_parameterized_join(
- urgent_assigned_tasks => { urgency_threshold => 200 },
-)->count, 1, 'not joined';
+# my $join_with_range = sub {
+# return shift->with_parameterized_join(
+# tasks_in_urgency_range => {
+# min => $_[0],
+# max => $_[1],
+# },
+# );
+# };
+
+ my $search = sub {
+ return scalar shift->search(
+ { 'me.name' => { -like => 'Bob%' } },
+ {
+ '+select' => [{
+ count => \['urgent_assigned_tasks.id'],
+ }],
+ '+as' => ['task_count'],
+ },
+ );
+ };
+
+ my $fetch_count = sub {
+ return shift->next->get_column('task_count');
+ };
+
+ subtest 'simple filter' => sub {
+ is $people->$join_with_min(19)->$search->$fetch_count,
+ 2, 'filter min 19';
+ is $people->$join_with_min(29)->$search->$fetch_count,
+ 1, 'filter min 29';
+ is $people->$join_with_min(39)->$search->$fetch_count,
+ 0, 'filter min 39';
+ };
+
+ subtest 'multiple filters' => sub {
+ my $rs1 = $people->$join_with_min(19)->$search;
+ my $rs2 = $people->$join_with_min(29)->$search;
+ is $rs1->$fetch_count, 2, 'first';
+ is $rs2->$fetch_count, 1, 'second';
+ };
+
+ subtest 'overrides' => sub {
+ is $people
+ ->$join_with_min(190)
+ ->$join_with_min(19)
+ ->$search
+ ->$fetch_count,
+ 2, 'overridden parameter';
+ };
+
+# subtest 'multi parameter' => sub {
+# is $people->$join_with_range(10, 30)->$search->$fetch_count,
+# 3, 'full range';
+# };
+};
+
+done_testing;
]
);
+__PACKAGE__->parameterized_has_many(
+ tasks_in_urgency_range => 'My::Schema::Result::Task',
+ [ [ qw( min max ) ], sub {
+ my $args = shift;
+ +{
+ "$args->{foreign_alias}.assigned_to_id" =>
+ { -ident => "$args->{self_alias}.id" },
+ "$args->{foreign_alias}.urgency" =>
+ { '>=', $_{min} },
+ "$args->{foreign_alias}.urgency" =>
+ { '<=', $_{max} },
+ }
+ }
+ ]
+);
+
1;