refactored value string building
matthewt [Tue, 29 Jan 2008 07:40:51 +0000 (07:40 +0000)]
lib/Reaction/UI/ViewPort/Field.pm
lib/Reaction/UI/ViewPort/Field/ChooseOne.pm
lib/Reaction/UI/ViewPort/Field/DateTime.pm
lib/Reaction/UI/ViewPort/Field/Mutable/ChooseMany.pm
lib/Reaction/UI/ViewPort/Field/Mutable/ChooseOne.pm
lib/Reaction/UI/ViewPort/Field/RelatedObject.pm

index 007946b..bd02802 100644 (file)
@@ -6,7 +6,7 @@ use aliased 'Reaction::Meta::InterfaceModel::Object::ParameterAttribute';
 
 class Field is 'Reaction::UI::ViewPort', which {
 
-  has value        => (is => 'rw', lazy_build => 1);
+  has value        => (is => 'rw', lazy_build => 1, clearer => 'clear_value');
   has name         => (is => 'rw', isa => 'Str', lazy_build => 1);
   has label        => (is => 'rw', isa => 'Str', lazy_build => 1);
   has value_string => (is => 'rw', isa => 'Str', lazy_build => 1);
@@ -17,28 +17,47 @@ class Field is 'Reaction::UI::ViewPort', which {
   implements adopt_value => as {};
 
   implements _build_name => as { shift->attribute->name };
-  implements _build_value_string => as { shift->value };
 
   implements _build_label => as {
     join(' ', map { ucfirst } split('_', shift->name));
   };
 
-  #unlazify and move it to build. to deal with array use typeconstraints and coercions
   implements _build_value => as {
     my ($self) = @_;
     my $reader = $self->attribute->get_read_method;
+    return $self->model->$reader;
+  };
+
+  implements _model_has_value => as {
+    my ($self) = @_;
     my $predicate = $self->attribute->predicate;
 
     if (!$predicate || $self->model->$predicate
         || ($self->attribute->is_lazy
             && !$self->attribute->is_lazy_fail)
       ) {
-      return $self->model->$reader;
+      # either model attribute has a value now or can build it
+      return 1;
     }
-    return $self->_empty_value;
+    return 0;
+  };
+
+  implements _build_value_string => as {
+    my ($self) = @_;
+    # XXX need the defined test because the IM lazy builds from
+    # the model and DBIC can have nullable fields and DBIC doesn't
+    # have a way to tell us that doesn't force value inflation (extra
+    # SELECTs for belongs_to) so basically we're screwed.
+    return ($self->_model_has_value && defined($self->value)
+              ? $self->_value_string_from_value
+              : $self->_empty_string_value);
+  };
+
+  implements _value_string_from_value => as {
+    shift->value;
   };
 
-  implements _empty_value => as { '' };
+  implements _empty_string_value => as { '' };
 
 };
 
index cb34b92..a44314e 100644 (file)
@@ -34,8 +34,6 @@ class ChooseOne is 'Reaction::UI::ViewPort::Field', which {
     }
   };
 
-  implements _empty_value => as { undef };
-
   implements _build_valid_values => as {
     my $self = shift;
     return [ $self->attribute->all_valid_values($self->action) ];
index 51232cf..e89fc47 100644 (file)
@@ -12,21 +12,13 @@ class DateTime is Field, which {
     isa => 'Str', is => 'rw', required => 1, default => sub { "%F %H:%M:%S" }
   );
 
-  implements _build_value_string => as {
+  around _value_string_from_value => sub {
+    my $orig = shift;
     my $self = shift;
-    # XXX
-    #<mst> aha, I know why the fucker's lazy
-    #<mst> it's because if value's calculated
-    #<mst> it needs to be possible to clear it
-    #<mst> eval { $self->value } ... is probably the best solution atm
-    my $value = $self->value;
-    return '' unless blessed $value;
     my $format = $self->value_string_default_format;
-    return $value->strftime($format);
+    return $self->$orig(@_)->strftime($format);
   };
 
-  implements _empty_value => as { undef };
-
 };
 
 1;
index 8108633..e6702f7 100644 (file)
@@ -33,7 +33,7 @@ class ChooseMany is 'Reaction::UI::ViewPort::Field', which {
     return super() || [];
   };
 
-  implements _build_value_string => as {
+  around _value_string_from_value => sub {
     my $self = shift;
     join ", ", (map {$self->obj_to_name($_->{value}) } @{ $self->current_value_choices })
   };
index 4289282..c7d40f9 100644 (file)
@@ -29,11 +29,13 @@ class ChooseOne is 'Reaction::UI::ViewPort::Field', which {
     $orig->($self, $value);
   };
 
-  implements _build_value_string => as {
+  around _value_string_from_value => sub {
+    my $orig = shift;
     my $self = shift;
-    my $value = $self->value;
+    my $value = $self->$orig(@_);
     return $self->obj_to_name($value->{value}) if Scalar::Util::blessed($value);
-    $value;
+    return $self->obj_to_name($value) if blessed $value;
+    return "$value"; # force stringify. might work. probably won't.
   };
 
   implements is_current_value => as {
index 23d715d..3a3354f 100644 (file)
@@ -9,15 +9,13 @@ class RelatedObject is 'Reaction::UI::ViewPort::Field', which {
     isa => 'Str', is => 'ro', required => 1, default => sub { 'display_name' },
   );
 
-  implements _build_value_string => as {
+  around _value_string_from_value => sub {
+    my $orig = shift;
     my $self = shift;
     my $meth = $self->value_map_method;
-    my $value = $self->value;
-    return blessed($value) ? $value->$meth : $value;
+    return $self->$orig(@_)->$meth;
   };
 
-  implements _empty_value => as { undef };
-
 };
 
 1;