[Rt-commit] r3889 - in Jifty-DBI/trunk: . lib/Jifty/DBI t
ruz at bestpractical.com
ruz at bestpractical.com
Sun Sep 25 04:59:44 EDT 2005
Author: ruz
Date: Sun Sep 25 04:59:44 2005
New Revision: 3889
Modified:
Jifty-DBI/trunk/ (props changed)
Jifty-DBI/trunk/lib/Jifty/DBI/Column.pm
Jifty-DBI/trunk/lib/Jifty/DBI/Filter.pm
Jifty-DBI/trunk/lib/Jifty/DBI/Record.pm
Jifty-DBI/trunk/t/01records.t
Jifty-DBI/trunk/t/06filter.t
Log:
r2508 at cubic-pc: cubic | 2005-09-24 13:48:27 +0400
* Column and Record classes inherit interface from HasFilter
* moved filters handling from Column to Record class
* Filter class has new accessor 'record', so filters has access to
record filter is applied
* default record's filter 'Jifty::DBI::Filter::Truncate'
* Record->__set accept undef values and set column to NULL
* __set checks value equality only if we have required data
otherwise just update
* basic filters tests
Modified: Jifty-DBI/trunk/lib/Jifty/DBI/Column.pm
==============================================================================
--- Jifty-DBI/trunk/lib/Jifty/DBI/Column.pm (original)
+++ Jifty-DBI/trunk/lib/Jifty/DBI/Column.pm Sun Sep 25 04:59:44 2005
@@ -3,10 +3,9 @@
package Jifty::DBI::Column;
-use base qw/Class::Accessor/;
+use base qw/Class::Accessor Jifty::DBI::HasFilters/;
use UNIVERSAL::require;
-
__PACKAGE__->mk_accessors qw/
name
type
@@ -17,12 +16,9 @@
length
refers_to_collection_class
refers_to_record_class
- alias_for_column
- filters
- output_filters
+ alias_for_column
/;
-# input_filters
=head1 NAME
@@ -60,51 +56,4 @@
*write = \&writable;
-sub decode_value {
- my $self = shift;
- my $value_ref = shift;
- $self->_apply_filters( value_ref => $value_ref,
- filters => $self->output_filters,
- action => 'decode'
- );
-}
-
-sub input_filters {
- my $self = shift;
-
- return (['Jifty::DBI::Filter::Truncate']);
-
-}
-
-
-
-sub encode_value {
- my $self = shift;
- my $value_ref = shift;
- $self->_apply_filters( value_ref => $value_ref,
- filters =>
- $self->input_filters,
- action => 'encode'
- );
-}
-
-
-sub _apply_filters {
- my $self = shift;
- my %args = (
- value_ref => undef,
- filters => undef,
- action => undef,
- @_
- );
- my $action = $args{'action'};
- foreach my $filter_class ( @{ $args{filters} } ) {
- $filter_class->require();
- my $filter = $filter_class->new( column => $self, value_ref => $args{'value_ref'});
- # XXX TODO error proof this
- $filter->$action();
- }
-}
-
-
1;
Modified: Jifty-DBI/trunk/lib/Jifty/DBI/Filter.pm
==============================================================================
--- Jifty-DBI/trunk/lib/Jifty/DBI/Filter.pm (original)
+++ Jifty-DBI/trunk/lib/Jifty/DBI/Filter.pm Sun Sep 25 04:59:44 2005
@@ -4,7 +4,7 @@
package Jifty::DBI::Filter;
use base 'Class::Accessor';
-__PACKAGE__->mk_accessors(qw(column value_ref));
+__PACKAGE__->mk_accessors(qw(record column value_ref));
=head2 new
@@ -52,12 +52,8 @@
from flattening a L<DateTime> object into an ISO date to making sure
that data is utf8 clean.
-
-
-
=cut
-
sub encode {
}
@@ -68,7 +64,6 @@
from flattening a L<DateTime> object into an ISO date to making sure
that data is utf8 clean.
-
=cut
sub decode {
Modified: Jifty-DBI/trunk/lib/Jifty/DBI/Record.pm
==============================================================================
--- Jifty-DBI/trunk/lib/Jifty/DBI/Record.pm (original)
+++ Jifty-DBI/trunk/lib/Jifty/DBI/Record.pm Sun Sep 25 04:59:44 2005
@@ -4,12 +4,15 @@
use warnings;
use vars qw($AUTOLOAD);
-use Class::ReturnValue;
-use Lingua::EN::Inflect;
-use Jifty::DBI::Column;
-use UNIVERSAL::require;
-
-use base qw/Class::Data::Inheritable/;
+use Class::ReturnValue ();
+use Lingua::EN::Inflect ();
+use Jifty::DBI::Column ();
+use UNIVERSAL::require ();
+
+use base qw/
+ Class::Data::Inheritable
+ Jifty::DBI::HasFilters
+ /;
Jifty::DBI::Record->mk_classdata('COLUMNS');
@@ -240,6 +243,7 @@
bless( $self, $class );
$self->_init_columns() unless $self->COLUMNS;
+ $self->input_filters( 'Jifty::DBI::Filter::Truncate' );
$self->_init(@_);
@@ -452,31 +456,29 @@
for my $column_name ( keys %$schema ) {
my $column = $self->add_column($column_name);
- # Default, everything readable and writable
- $column->readable(1);
+ my $meta = $schema->{ $column_name } || {};
- if ( $schema->{$column_name}{'read'} ) {
- $column->readable( $schema->{$column_name}{'read'});
- } else {
- $column->readable(1);
- }
+ # Default, everything readable
+ $column->readable( delete $meta->{'read'} || 1 );
- if ( $schema->{$column_name}{'write'} ) {
- $column->writable( $schema->{$column_name}{'write'});
+ # Default, everything writable except columns of the pkey
+ if ( $meta->{'write'} ) {
+ $column->writable( $meta->{'write'} );
} elsif (not defined $column->writable) { # don't want to make pkeys writable
$column->writable(1);
}
+ delete $meta->{'write'};
-
# Next time, all-lower hash keys
- my $type = $schema->{$column_name}{'type'} || $schema->{$column_name}{'TYPE'};
+ my $type = delete $meta->{'type'} ||
+ delete $meta->{'TYPE'};
if ($type) {
$column->type($type);
-
}
- my $refclass = $schema->{$column_name}{'REFERENCES'} || $schema->{$column_name}{'references'};
+ my $refclass = delete $meta->{'REFERENCES'} ||
+ delete $meta->{'references'};
if ($refclass) {
$refclass->require();
@@ -486,7 +488,7 @@
my $virtual_column = $self->add_column($1);
$virtual_column->refers_to_record_class($refclass);
$virtual_column->alias_for_column($column_name);
- $virtual_column->readable( $schema->{$column_name}{'read'} || 1);
+ $virtual_column->readable( delete $meta->{'read'} || 1);
}
else {
$column->refers_to_record_class($refclass);
@@ -500,6 +502,10 @@
warn "Error: $refclass neither Record nor Collection";
}
}
+ for my $attr( keys %$meta) {
+ next unless $column->can( $attr );
+ $column->$attr( $meta->{$attr} );
+ }
}
}
@@ -582,8 +588,7 @@
sub column {
my $self = shift;
- my $name = shift;
- $name = lc $name;
+ my $name = lc( shift || '');
return undef unless $self->COLUMNS and $self->COLUMNS->{$name};
return $self->COLUMNS->{$name} ;
@@ -651,10 +656,16 @@
my ($value) = eval { $sth->fetchrow_array() };
warn $@ if $@;
- $column->decode_value(\$value);
$self->{'values'}{$column->name} = $value;
$self->{'fetched'}{$column->name} = 1;
}
+ if( $self->{'fetched'}{$column->name} &&
+ !$self->{'decoded'}{$column->name} ) {
+ $self->_apply_output_filters( column => $column,
+ value_ref => \$self->{'values'}{$column->name},
+ );
+ $self->{'decoded'}{$column->name} = 1;
+ }
return $self->{'values'}{$column->name};
}
@@ -713,33 +724,26 @@
return ( $ret->return_value );
}
-
- $column->encode_value(\$args{'value'});
-
+ $self->_apply_input_filters( column => $column, value_ref => \$args{'value'} );
- if ( !defined( $args{'value'} ) ) {
- $ret->as_array( 0, "No value passed to _set" );
- $ret->as_error(
- errno => 2,
- do_backtrace => 0,
- message => "No value passed to _set"
- );
- return ( $ret->return_value );
+ # if value is not fetched or it's allready decoded
+ # then we don't check eqality
+ # we also don't call __value because it decodes value, but
+ # we need encoded value
+ if ( $self->{'fetched'}{$column->name} ||
+ !$self->{'decoded'}{$column->name} ) {
+ if( ( !defined $args{'value'} && !defined $self->{'values'}{$column->name} ) ||
+ ( defined $args{'value'} && defined $self->{'values'}{$column->name} &&
+ $args{'value'} eq $self->{'values'}{$column->name} ) ) {
+ $ret->as_array( 0, "That is already the current value" );
+ $ret->as_error(
+ errno => 1,
+ do_backtrace => 0,
+ message => "That is already the current value"
+ );
+ return ( $ret->return_value );
+ }
}
- elsif ( ( defined $self->__value($column->name) )
- and ( $args{'value'} eq $self->__value($column->name) ) )
- {
- $ret->as_array( 0, "That is already the current value" );
- $ret->as_error(
- errno => 1,
- do_backtrace => 0,
- message => "That is already the current value"
- );
- return ( $ret->return_value );
- }
-
-
-
my $method = "validate_" . $column->name;
unless ( $self->$method( $args{'value'} ) ) {
@@ -793,6 +797,7 @@
}
else {
$self->{'values'}->{$column->name} = $unmunged_value;
+ $self->{'decoded'}{$column->name} = 0;
}
$ret->as_array( 1, "The new value has been set." );
return ( $ret->return_value );
@@ -928,6 +933,7 @@
}
$self->{'values'} = $hashref;
+ $self->{'decoded'} = {};
return $self->id();
}
@@ -950,6 +956,7 @@
$self->{'values'} = $sth->fetchrow_hashref;
$self->{'fetched'} = {};
+ $self->{'decoded'} = {};
if ( !$self->{'values'} && $sth->err ) {
return ( 0, "Couldn't fetch row: " . $sth->err );
}
@@ -994,7 +1001,9 @@
}
- $column->encode_value( \$attribs{$column_name});
+ $self->_apply_input_filters( column => $column,
+ value_ref => \$attribs{$column_name},
+ );
}
unless ( $self->_handle->knows_blobs ) {
@@ -1112,6 +1121,53 @@
sub schema {}
+sub _filters
+{
+ my $self = shift;
+ my %args = ( direction => 'input', column => undef, @_ );
+
+ my @filters = ();
+ my @objs = ($self, $args{'column'}, $self->_handle);
+ @objs = reverse @objs if $args{'direction'} eq 'output';
+ my $method = $args{'direction'} ."_filters";
+ foreach my $obj( @objs ) {
+ push @filters, $obj->$method();
+ }
+ return grep $_, @filters;
+}
+
+sub _apply_input_filters {
+ return (shift)->_apply_filters(direction => 'input', @_);
+}
+sub _apply_output_filters {
+ return (shift)->_apply_filters(direction => 'output', @_);
+}
+sub _apply_filters {
+ my $self = shift;
+ my %args = ( direction => 'input',
+ column => undef,
+ value_ref => undef,
+ @_
+ );
+
+ my @filters = $self->_filters( %args );
+ my $action = $args{'direction'} eq 'output'? 'decode' : 'encode';
+ foreach my $filter_class ( @filters ) {
+ local $UNIVERSAL::require::ERROR;
+ $filter_class->require();
+ if( $UNIVERSAL::require::ERROR ) {
+ warn $UNIVERSAL::require::ERROR;
+ next;
+ }
+ my $filter = $filter_class->new( record => $self,
+ column => $args{'column'},
+ value_ref => $args{'value_ref'},
+ );
+ # XXX TODO error proof this
+ $filter->$action();
+ }
+}
+
1;
__END__
Modified: Jifty-DBI/trunk/t/01records.t
==============================================================================
--- Jifty-DBI/trunk/t/01records.t (original)
+++ Jifty-DBI/trunk/t/01records.t Sun Sep 25 04:59:44 2005
@@ -8,7 +8,7 @@
BEGIN { require "t/utils.pl" }
our (@available_drivers);
-use constant TESTS_PER_DRIVER => 63;
+use constant TESTS_PER_DRIVER => 61;
my $total = scalar(@available_drivers) * TESTS_PER_DRIVER;
plan tests => $total;
@@ -80,19 +80,14 @@
is($rec->name, '12345678901234', "Truncated on update");
-# Test unicode truncation:
- my $univalue = "這是個測試";
- ($val,$msg) = $rec->set_name($univalue.$univalue);
- ok($val, $msg) ;
- is($rec->name, '這是個測');
-
-
-
# make sure we do _not_ truncate things which should not be truncated
($val,$msg) = $rec->set_employee_id('1234567890');
ok($val, $msg) ;
is($rec->employee_id, '1234567890', "Did not truncate id on create");
+ #delete prev record
+ $rec->delete;
+
# make sure we do truncation on create
my $newrec = TestApp::Address->new($handle);
my $newid = $newrec->create( name => '1234567890123456789012345678901234567890',
@@ -181,10 +176,11 @@
is( ($val->as_array)[1], 'Illegal value for name', "correct error message" );
is( $rec->name, 'Obra', "old value is still there");
# XXX TODO FIXME: this test cover current implementation that is broken //RUZ
+# fixed, now we can set undef values(NULLs)
$val = $rec->set_name( );
- isa_ok( $val, 'Class::ReturnValue', "couldn't set empty/undef value, error returned");
- is( ($val->as_array)[1], "No value passed to _set", "correct error message" );
- is( $rec->name, 'Obra', "old value is still there");
+ isa_ok( $val, 'Class::ReturnValue', "set empty/undef/NULL value");
+ is( ($val->as_array)[1], "The new value has been set.", "correct error message" );
+ is( $rec->name, undef, "new value is undef, NULL in DB");
# deletes
$newrec = TestApp::Address->new($handle);
@@ -208,7 +204,7 @@
sub validate_name
{
my ($self, $value) = @_;
- return 0 if $value =~ /invalid/i;
+ return 0 if $value && $value =~ /invalid/i;
return 1;
}
Modified: Jifty-DBI/trunk/t/06filter.t
==============================================================================
--- Jifty-DBI/trunk/t/06filter.t (original)
+++ Jifty-DBI/trunk/t/06filter.t Sun Sep 25 04:59:44 2005
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+use Test::More;
+BEGIN { require "t/utils.pl" }
+plan tests => 6;
+# test for Jifty::DBI::Filter class only
+# create new t/06filter_*.t files for specific filters
+
+# DB independat tests
+use_ok('Jifty::DBI::Filter');
+my $filter = new Jifty::DBI::Filter;
+isa_ok( $filter, 'Jifty::DBI::Filter' );
+is( $filter->column, undef, "empty column value" );
+is( $filter->value_ref, undef, "empty value reference" );
+
+$filter->column( 'my column' );
+is( $filter->column, 'my column', "successfuly set column" );
+$filter->value_ref( 'my value_ref' );
+is( $filter->value_ref, 'my value_ref', "successfuly set value_ref" );
+
+# methods do nothing, but just in case
+$filter->decode;
+$filter->encode;
+
+1;
More information about the Rt-commit
mailing list