use strict; use warnings; use Test::More; use Test::Exception; use lib qw(t/lib); use DBICTest; my $from_storage_ran = 0; my $to_storage_ran = 0; my $schema = DBICTest->init_schema(); DBICTest::Schema::Artist->load_components(qw(FilterColumn InflateColumn)); DBICTest::Schema::Artist->filter_column(rank => { filter_from_storage => sub { $from_storage_ran++; $_[1] * 2 }, filter_to_storage => sub { $to_storage_ran++; $_[1] / 2 }, }); Class::C3->reinitialize(); my $artist = $schema->resultset('Artist')->create( { rank => 20 } ); # this should be using the cursor directly, no inflation/processing of any sort my ($raw_db_rank) = $schema->resultset('Artist') ->search ($artist->ident_condition) ->get_column('rank') ->_resultset ->cursor ->next; is ($raw_db_rank, 10, 'INSERT: correctly unfiltered on insertion'); for my $reloaded (0, 1) { my $test = $reloaded ? 'reloaded' : 'stored'; $artist->discard_changes if $reloaded; is( $artist->rank , 20, "got $test filtered rank" ); } $artist->update; $artist->discard_changes; is( $artist->rank , 20, "got filtered rank" ); $artist->update ({ rank => 40 }); ($raw_db_rank) = $schema->resultset('Artist') ->search ($artist->ident_condition) ->get_column('rank') ->_resultset ->cursor ->next; is ($raw_db_rank, 20, 'UPDATE: correctly unflitered on update'); $artist->discard_changes; $artist->rank(40); ok( !$artist->is_column_changed('rank'), 'column is not dirty after setting the same value' ); MC: { my $cd = $schema->resultset('CD')->create({ artist => { rank => 20 }, title => 'fun time city!', year => 'forevertime', }); ($raw_db_rank) = $schema->resultset('Artist') ->search ($cd->artist->ident_condition) ->get_column('rank') ->_resultset ->cursor ->next; is $raw_db_rank, 10, 'artist rank gets correctly unfiltered w/ MC'; is $cd->artist->rank, 20, 'artist rank gets correctly filtered w/ MC'; } CACHE_TEST: { my $expected_from = $from_storage_ran; my $expected_to = $to_storage_ran; # ensure we are creating a fresh obj $artist = $schema->resultset('Artist')->single($artist->ident_condition); is $from_storage_ran, $expected_from, 'from has not run yet'; is $to_storage_ran, $expected_to, 'to has not run yet'; $artist->rank; cmp_ok ( $artist->get_filtered_column('rank'), '!=', $artist->get_column('rank'), 'filter/unfilter differ' ); is $from_storage_ran, ++$expected_from, 'from ran once, therefor caches'; is $to_storage_ran, $expected_to, 'to did not run'; $artist->rank(6); is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, ++$expected_to, 'to ran once'; ok ($artist->is_column_changed ('rank'), 'Column marked as dirty'); $artist->rank; is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, $expected_to, 'to did not run'; $artist->update; $artist->set_column(rank => 3); ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same set_column value'); is ($artist->rank, '6', 'Column set properly (cache blown)'); is $from_storage_ran, ++$expected_from, 'from ran once (set_column blew cache)'; is $to_storage_ran, $expected_to, 'to did not run'; $artist->rank(6); ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on same accessor-set value'); is ($artist->rank, '6', 'Column set properly'); is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, $expected_to, 'to did not run'; $artist->store_column(rank => 4); ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on differing store_column value'); is ($artist->rank, '8', 'Cache properly blown'); is $from_storage_ran, ++$expected_from, 'from did not run'; is $to_storage_ran, $expected_to, 'to did not run'; } IC_DIE: { dies_ok { DBICTest::Schema::Artist->inflate_column(rank => { inflate => sub {}, deflate => sub {} } ); } q(Can't inflate column after filter column); DBICTest::Schema::Artist->inflate_column(name => { inflate => sub {}, deflate => sub {} } ); dies_ok { DBICTest::Schema::Artist->filter_column(name => { filter_to_storage => sub {}, filter_from_storage => sub {} }); } q(Can't filter column after inflate column); } # test when we do not set both filter_from_storage/filter_to_storage DBICTest::Schema::Artist->filter_column(rank => { filter_to_storage => sub { $to_storage_ran++; $_[1] }, }); Class::C3->reinitialize(); ASYMMETRIC_TO_TEST: { # initialise value $artist->rank(20); $artist->update; my $expected_from = $from_storage_ran; my $expected_to = $to_storage_ran; $artist->rank(10); ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on accessor-set value'); is ($artist->rank, '10', 'Column set properly'); is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, ++$expected_to, 'to did run'; $artist->discard_changes; is ($artist->rank, '20', 'Column set properly'); is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, $expected_to, 'to did not run'; } DBICTest::Schema::Artist->filter_column(rank => { filter_from_storage => sub { $from_storage_ran++; $_[1] }, }); Class::C3->reinitialize(); ASYMMETRIC_FROM_TEST: { # initialise value $artist->rank(23); $artist->update; my $expected_from = $from_storage_ran; my $expected_to = $to_storage_ran; $artist->rank(13); ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on accessor-set value'); is ($artist->rank, '13', 'Column set properly'); is $from_storage_ran, $expected_from, 'from did not run'; is $to_storage_ran, $expected_to, 'to did not run'; $artist->discard_changes; is ($artist->rank, '23', 'Column set properly'); is $from_storage_ran, ++$expected_from, 'from did run'; is $to_storage_ran, $expected_to, 'to did not run'; } throws_ok { DBICTest::Schema::Artist->filter_column( rank => {} ) } qr/\QAn invocation of filter_column() must specify either a filter_from_storage or filter_to_storage/, 'Correctly throws exception for empty attributes' ; done_testing;