value_path will work fine for new-value binding, identity_path not required
[scpubgit/DX.git] / lib / DX / Predicate / MemberAt.pm
index 3874cb8..bde4bf1 100644 (file)
@@ -1,15 +1,12 @@
 package DX::Predicate::MemberAt;
 
-use DX::Utils qw(step INDICES_OF EXISTENCE_OF CONTENTS_OF);
+use DX::Utils qw(step INDICES_OF EXISTENCE_OF CONTENTS_OF string);
+use DX::ActionBuilder::ProxySetToAdd;
+use DX::ActionBuilder::Null;
 use DX::Class;
 
 with 'DX::Role::Predicate';
 
-# Thing I've ignored for the moment: set key, unset value
-# which for an add should result in an _make_equal style
-# bind-with-add-action I suspect, but I don't have a current use
-# case so punting while I get everything-the-fuck-else done
-
 sub _possible_resolution_list {
   my ($self, $coll, $key, $value) = @_;
   die "First argument to member_at must be a structured value"
@@ -37,19 +34,50 @@ sub _possible_resolution_list {
                 ],
               ],
             );
+          } elsif (
+            !$value->is_set
+            and $value->action_builder->isa('DX::ActionBuilder::UnsetValue')
+            and my $p = $coll->value_path
+          ) {
+            my @path = (@$p, $key->string_value);
+            my $ab = DX::ActionBuilder::ProxySetToAdd->new(
+              target_path => \@path,
+              proxy_to => $coll->action_builder,
+            );
+            my $set = $value->action_for_set_value(
+                        $value->but(
+                          action_builder => $ab
+                        )
+                      );
+            step(
+              actions => [ $set ],
+              depends_on => [
+                [ $value =>
+                  [ CONTENTS_OF ,=> $coll, $key->string_value ],
+                  [ CONTENTS_OF ,=> $value ],
+                ],
+              ],
+            );
           } else {
             ()
           }
         }
       : ()
     ),
-    ($key->can_set_value
+    (!$key->is_set
+     && $key->action_builder->isa('DX::ActionBuilder::UnsetValue')
       ? map {
-          my $set_key = $key->action_for_set_value($_);
+          my $set_key = DX::Action::SetValue->new(
+            target_path => $key->action_builder->target_path,
+            new_value => DX::ActionBuilder::Null->new(
+                           target_path => $key->action_builder->target_path,
+                         )->apply_to_value(string(my $kstr = $_))
+          );
           map $_->but_first($set_key)
                 ->but_with_dependencies_on(
                     [ undef ,=>
-                      [ EXISTENCE_OF ,=> $coll, $key->string_value ]
+                      [ EXISTENCE_OF ,=> $coll, $kstr ],
+                      [ CONTENTS_OF ,=> $key ],
                     ]
                   ),
             $self->_make_equal($coll->get_member_at($_), $value);