From: Brian Cassidy Date: Fri, 12 Jun 2009 12:40:19 +0000 (-0300) Subject: Merge branch 'master' of dbsrgits@jules.scsys.co.uk:DBIx-Class-DateTime-Epoch X-Git-Tag: 0.06~3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d99b69cb6b1b3867dab464f229bc891aaabf1a55;hp=30ed2df103a965ddf5b0f584068b53a668dc0adb;p=dbsrgits%2FDBIx-Class-DateTime-Epoch.git Merge branch 'master' of dbsrgits@jules.scsys.co.uk:DBIx-Class-DateTime-Epoch --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9a77f9c --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +META.yml +Makefile +Makefile.old +cover_db +blib +inc +pm_to_blib +MANIFEST* +!MANIFEST.SKIP +*~ diff --git a/Changes b/Changes new file mode 100644 index 0000000..98e3d89 --- /dev/null +++ b/Changes @@ -0,0 +1,23 @@ +Revision history for Perl extension DBIx::Class::DateTime::Epoch. + +0.05 Mon Jun 01 2009 + [ THING THAT WILL NO LONGER BREAK YOUR CODE ] + - added back-compat for the "epoch => 1", etc syntax + +0.04 Tue May 26 2009 + [ THINGS THAT WILL BREAK YOUR CODE ] + - refactor module to itegrate with InflateColumn::DateTime and TimeStamp. + Requires DBIx::Class 0.08103 and DBIx::Class::TimeStamp 0.07. + Please read the new documentation. + + [ ENHANCEMENTS ] + - switch to Module::Install + +0.03 Wed Apr 25 2007 + - don't override user-supplied values for update() + +0.02 Mon Jul 17 2006 + - Re-release onto CPAN + +0.01 Wed Mar 22 2006 + - original version; diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP new file mode 100644 index 0000000..c7cefa4 --- /dev/null +++ b/MANIFEST.SKIP @@ -0,0 +1,31 @@ +# Avoid version control files. +\bRCS\b +\bCVS\b +,v$ +\B\.svn\b +\B\.git\b +\.gitignore + +# Avoid Makemaker generated and utility files. +\bMakefile$ +\bblib +\bMakeMaker-\d +\bpm_to_blib$ +\bblibdirs$ +^MANIFEST\.SKIP$ + +# Avoid Module::Build generated and utility files. +\bBuild$ +\b_build + +# Avoid temp and backup files. +~$ +\.tmp$ +\.old$ +\.bak$ +\#$ +\b\.# +\.DS_Store$ + +# No tarballs! +\.gz$ diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..ff37cc1 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,21 @@ +use inc::Module::Install 0.87; + +if( -e 'MANIFEST.SKIP' ) { + system( 'pod2text lib/DBIx/Class/DateTime/Epoch.pm > README' ); +} + +perl_version '5.006001'; + +name 'DBIx-Class-DateTime-Epoch'; +all_from 'lib/DBIx/Class/DateTime/Epoch.pm'; + +requires 'DBIx::Class' => '0.08103'; # InflateColumn::DateTime overriding possible +requires 'DBIx::Class::TimeStamp' => '0.07'; # removes data_type checking +requires 'DateTime'; + +test_requires 'Test::More'; +test_requires 'DBICx::TestDatabase'; + +repository 'http://github.com/bricas/dbix-class-datetime-epoch'; + +WriteAll; diff --git a/lib/DBIx/Class/DateTime/Epoch.pm b/lib/DBIx/Class/DateTime/Epoch.pm new file mode 100644 index 0000000..a719233 --- /dev/null +++ b/lib/DBIx/Class/DateTime/Epoch.pm @@ -0,0 +1,159 @@ +package DBIx::Class::DateTime::Epoch; + +use strict; +use warnings; + +our $VERSION = '0.05'; + +use base qw( DBIx::Class ); + +use DateTime; + +__PACKAGE__->load_components( qw( InflateColumn::DateTime ) ); + +# back compat +sub add_columns { + my( $class, @cols ) = @_; + my @columns; + + while (my $col = shift @cols) { + my $info = ref $cols[0] ? shift @cols : {}; + + if( my $type = delete $info->{ epoch } ) { + $info->{ inflate_datetime } = 'epoch'; + + if( $type =~ m{^[cm]time$} ) { + __PACKAGE__->load_components( 'TimeStamp' ); + $info->{ set_on_create } = 1; + $info->{ set_on_update } = 1 if $type eq 'mtime'; + } + } + + push @columns, $col => $info; + + } + + $class->next::method( @columns ); +} + +sub _inflate_to_datetime { + my( $self, $value, $info, @rest ) = @_; + $self->next::method( $value, $info, @rest ) + unless $info->{ data_type } =~ m{int} || $info->{ inflate_datetime } eq 'epoch'; + + return DateTime->from_epoch( epoch => $value ); +} + +sub _deflate_from_datetime { + my( $self, $value, $info, @rest ) = @_; + $self->next::method( $value, $info, @rest ) + unless $info->{ data_type } =~ m{int} || $info->{ inflate_datetime } eq 'epoch'; + + return $value->epoch; +} + +1; + +__END__ + +=head1 NAME + +DBIx::Class::DateTime::Epoch - Automatic inflation/deflation of epoch-based columns to/from DateTime objects + +=head1 SYNOPSIS + + package MySchema::Foo; + + use base qw( DBIx::Class ); + + __PACKAGE__->load_components( qw( DateTime::Epoch TimeStamp Core ) ); + __PACKAGE__->add_columns( + name => { + data_type => 'varchar', + size => 10, + }, + bar => { # epoch stored as an int + data_type => 'bigint', + inflate_datetime => 1, + }, + baz => { # epoch stored as a string + data_type => 'varchar', + size => 50, + inflate_datetime => 'epoch', + }, + # working in conjunction with DBIx::Class::TimeStamp + creation_time => { + data_type => 'bigint', + inflate_datetime => 1, + set_on_create => 1, + }, + modification_time => { + data_type => 'bigint', + inflate_datetime => 1, + set_on_create => 1, + set_on_update => 1, + } + ); + +=head1 DESCRIPTION + +This module automatically inflates/deflates DateTime objects from/to epoch +values for the specified columns. This module is essentially an extension to +L so all of the settings, including +C and C, are also valid. + +A column will be recognized as an epoch time given one of the following scenarios: + +=over 4 + +=item * C is an C of some sort and C is also set to a true value + +=item * C is some other value (e.g. C) and C is explicitly set to C. + +=back + +L can also be used in conjunction with this module to support +epoch-based columns that are automatically set on creation of a row and updated subsequent +modifications. + +=head1 METHODS + +=head2 add_columns( ) + +Provides backwards compatibility with the older DateTime::Epoch API. + +=head2 _inflate_to_datetime( ) + +Overrides column inflation to use Cfrom_epoch>. + +=head2 _deflate_from_datetime( ) + +Overrides column deflation to call C on the column value. + +=head1 SEE ALSO + +=over 4 + +=item * DBIx::Class + +=item * DBIx::Class::TimeStamp + +=item * DateTime + +=back + +=head1 AUTHORS + +Brian Cassidy Ebricas@cpan.orgE + +Adam Paynter Eadapay@cpan.orgE + +=head1 COPYRIGHT AND LICENSE + +Copyright 2006-2009 by Brian Cassidy + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself. + +=cut + diff --git a/t/01-use.t b/t/01-use.t new file mode 100644 index 0000000..4bef453 --- /dev/null +++ b/t/01-use.t @@ -0,0 +1,8 @@ +use strict; +use warnings; + +use Test::More tests => 1; + +BEGIN { + use_ok( 'DBIx::Class::DateTime::Epoch' ); +} diff --git a/t/02-schema.t b/t/02-schema.t new file mode 100644 index 0000000..66f3664 --- /dev/null +++ b/t/02-schema.t @@ -0,0 +1,53 @@ +use strict; +use warnings; + +use lib 't/lib'; + +use Test::More tests => 15; + +use DBICx::TestDatabase; +use DateTime; +my $schema = DBICx::TestDatabase->new( 'MySchema' ); + +my $rs = $schema->resultset( 'Foo' ); + +{ + my $now = DateTime->now; + my $epoch = $now->epoch; + + $schema->populate( 'Foo', [ [ qw( id bar baz creation_time modification_time ) ], [ 1, ( $epoch ) x 4 ] ] ); + + { + my $row = $rs->find( 1 ); + + isa_ok( $row->bar, 'DateTime' ); + isa_ok( $row->baz, 'DateTime' ); + ok( $row->bar == $now, 'inflate: epoch as int' ); + ok( $row->baz == $now, 'inflate: epoch as varchar' ); + } + + { + $rs->create( { bar => $now, baz => $now } ); + my $row = $rs->find( 2 ); + + isa_ok( $row->bar, 'DateTime' ); + isa_ok( $row->baz, 'DateTime' ); + is( $row->get_column( 'bar' ), $epoch, 'deflate: epoch as int' ); + is( $row->get_column( 'baz' ), $epoch, 'deflate: epoch as varchar' ); + + # courtesy of TimeStamp + isa_ok( $row->creation_time, 'DateTime' ); # courtesy of TimeStamp + isa_ok( $row->modification_time, 'DateTime' ); + like( $row->get_column( 'creation_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + like( $row->get_column( 'modification_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + + my $mtime = $row->modification_time; + sleep( 1 ); + $row->update( { name => 'test' } ); + + $row = $rs->find( 2 ); + isa_ok( $row->modification_time, 'DateTime' ); + like( $row->get_column( 'modification_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + ok( $row->modification_time > $mtime, 'mtime column was updated' ); + } +} diff --git a/t/03-compat.t b/t/03-compat.t new file mode 100644 index 0000000..68fe75c --- /dev/null +++ b/t/03-compat.t @@ -0,0 +1,53 @@ +use strict; +use warnings; + +use lib 't/lib'; + +use Test::More tests => 15; + +use DBICx::TestDatabase; +use DateTime; +my $schema = DBICx::TestDatabase->new( 'MySchema' ); + +my $rs = $schema->resultset( 'FooCompat' ); + +{ + my $now = DateTime->now; + my $epoch = $now->epoch; + + $schema->populate( 'FooCompat', [ [ qw( id bar baz creation_time modification_time ) ], [ 1, ( $epoch ) x 4 ] ] ); + + { + my $row = $rs->find( 1 ); + + isa_ok( $row->bar, 'DateTime' ); + isa_ok( $row->baz, 'DateTime' ); + ok( $row->bar == $now, 'inflate: epoch as int' ); + ok( $row->baz == $now, 'inflate: epoch as varchar' ); + } + + { + $rs->create( { bar => $now, baz => $now } ); + my $row = $rs->find( 2 ); + + isa_ok( $row->bar, 'DateTime' ); + isa_ok( $row->baz, 'DateTime' ); + is( $row->get_column( 'bar' ), $epoch, 'deflate: epoch as int' ); + is( $row->get_column( 'baz' ), $epoch, 'deflate: epoch as varchar' ); + + # courtesy of TimeStamp + isa_ok( $row->creation_time, 'DateTime' ); # courtesy of TimeStamp + isa_ok( $row->modification_time, 'DateTime' ); + like( $row->get_column( 'creation_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + like( $row->get_column( 'modification_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + + my $mtime = $row->modification_time; + sleep( 1 ); + $row->update( { name => 'test' } ); + + $row = $rs->find( 2 ); + isa_ok( $row->modification_time, 'DateTime' ); + like( $row->get_column( 'modification_time' ), qr/^\d+$/, 'TimeStamp as epoch' ); + ok( $row->modification_time > $mtime, 'mtime column was updated' ); + } +} diff --git a/t/98-pod_coverage.t b/t/98-pod_coverage.t new file mode 100644 index 0000000..bb5c02e --- /dev/null +++ b/t/98-pod_coverage.t @@ -0,0 +1,7 @@ +use strict; +use warnings; + +use Test::More; +eval "use Test::Pod::Coverage 1.00"; +plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@; +all_pod_coverage_ok(); diff --git a/t/99-pod.t b/t/99-pod.t new file mode 100644 index 0000000..d6e05a9 --- /dev/null +++ b/t/99-pod.t @@ -0,0 +1,7 @@ +use strict; +use warnings; + +use Test::More; +eval "use Test::Pod 1.00"; +plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; +all_pod_files_ok(); diff --git a/t/lib/MySchema.pm b/t/lib/MySchema.pm new file mode 100644 index 0000000..9abbaa2 --- /dev/null +++ b/t/lib/MySchema.pm @@ -0,0 +1,10 @@ +package MySchema; + +use strict; +use warnings; + +use base qw( DBIx::Class::Schema ); + +__PACKAGE__->load_classes; + +1; diff --git a/t/lib/MySchema/Foo.pm b/t/lib/MySchema/Foo.pm new file mode 100644 index 0000000..ca4f5ba --- /dev/null +++ b/t/lib/MySchema/Foo.pm @@ -0,0 +1,46 @@ +package MySchema::Foo; + +use strict; +use warnings; + +use base qw( DBIx::Class ); + +__PACKAGE__->load_components( qw( DateTime::Epoch TimeStamp Core ) ); +__PACKAGE__->table( 'foo' ); +__PACKAGE__->add_columns( + id => { + data_type => 'bigint', + is_auto_increment => 1, + is_nullable => 0, + }, + name => { + data_type => 'varchar', + size => 10, + is_nullable => 1, + }, + bar => { # epoch stored as an int + data_type => 'bigint', + inflate_datetime => 1, + }, + baz => { # epoch stored as a string + data_type => 'varchar', + size => 50, + inflate_datetime => 'epoch', + }, + # working in conjunction with DBIx::Class::TimeStamp + creation_time => { + data_type => 'bigint', + inflate_datetime => 1, + set_on_create => 1, + }, + modification_time => { + data_type => 'bigint', + inflate_datetime => 1, + set_on_create => 1, + set_on_update => 1, + } +); + +__PACKAGE__->set_primary_key( 'id' ); + +1; diff --git a/t/lib/MySchema/FooCompat.pm b/t/lib/MySchema/FooCompat.pm new file mode 100644 index 0000000..a64494c --- /dev/null +++ b/t/lib/MySchema/FooCompat.pm @@ -0,0 +1,43 @@ +package MySchema::FooCompat; + +use strict; +use warnings; + +use base qw( DBIx::Class ); + +__PACKAGE__->load_components( qw( DateTime::Epoch Core ) ); +__PACKAGE__->table( 'foo_compat' ); +__PACKAGE__->add_columns( + id => { + data_type => 'bigint', + is_auto_increment => 1, + is_nullable => 0, + }, + name => { + data_type => 'varchar', + size => 10, + is_nullable => 1, + }, + bar => { # epoch stored as an int + data_type => 'bigint', + epoch => 1, + }, + baz => { # epoch stored as a string + data_type => 'varchar', + size => 50, + epoch => 1, + }, + # working in conjunction with DBIx::Class::TimeStamp + creation_time => { + data_type => 'bigint', + epoch => 'ctime', + }, + modification_time => { + data_type => 'bigint', + epoch => 'mtime', + } +); + +__PACKAGE__->set_primary_key( 'id' ); + +1;