From: Matt S Trout Date: Tue, 29 Sep 2015 01:09:56 +0000 (+0000) Subject: rework the local-izing code to navigate the maze of references correctly X-Git-Tag: v0.000001~11 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class-ParameterizedJoinHack.git;a=commitdiff_plain;h=ddc15dd9a0148153e815d474e43644cd0a792d85 rework the local-izing code to navigate the maze of references correctly --- diff --git a/lib/DBIx/Class/ParameterizedJoinHack.pm b/lib/DBIx/Class/ParameterizedJoinHack.pm index b0a5d7f..cfd5960 100644 --- a/lib/DBIx/Class/ParameterizedJoinHack.pm +++ b/lib/DBIx/Class/ParameterizedJoinHack.pm @@ -22,9 +22,9 @@ sub parameterized_has_many { 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; diff --git a/lib/DBIx/Class/ResultSet/ParameterizedJoinHack.pm b/lib/DBIx/Class/ResultSet/ParameterizedJoinHack.pm index 14ed789..4de2973 100644 --- a/lib/DBIx/Class/ResultSet/ParameterizedJoinHack.pm +++ b/lib/DBIx/Class/ResultSet/ParameterizedJoinHack.pm @@ -23,14 +23,22 @@ sub with_parameterized_join { ); } +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, @_) } diff --git a/t/00basic.t b/t/00basic.t index f24197b..23fe945 100644 --- a/t/00basic.t +++ b/t/00basic.t @@ -1,7 +1,7 @@ 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:'); @@ -27,14 +27,68 @@ $bob->create_related(assigned_tasks => { 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; diff --git a/t/lib/My/Schema/Result/Person.pm b/t/lib/My/Schema/Result/Person.pm index e38c12f..e89b3a6 100644 --- a/t/lib/My/Schema/Result/Person.pm +++ b/t/lib/My/Schema/Result/Person.pm @@ -34,4 +34,20 @@ __PACKAGE__->parameterized_has_many( ] ); +__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;