filter_from_storage => sub { $from_storage_ran++; $_[1] * 2 },
filter_to_storage => sub { $to_storage_ran++; $_[1] / 2 },
});
-Class::C3->reinitialize();
+Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO;
my $artist = $schema->resultset('Artist')->create( { rank => 20 } );
ok ($artist->is_column_changed ('rank'), 'Column marked as dirty');
$artist->rank;
- is $from_storage_ran, ++$expected_from, 'from ran once';
- is $to_storage_ran, $expected_to, 'to did not run';
-
- $artist->rank;
is $from_storage_ran, $expected_from, 'from did not run';
is $to_storage_ran, $expected_to, 'to did not run';
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';
+ is $to_storage_ran, ++$expected_to, 'to did run once (call in to set_column)';
$artist->store_column(rank => 4);
ok (! $artist->is_column_changed ('rank'), 'Column not marked as dirty on differing store_column value');
- is ($artist->rank, '6', 'Filtered column still contains old value (cache not blown)');
- is $from_storage_ran, $expected_from, 'from did not run';
+ 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';
+}
- $artist->set_column(rank => 4);
- TODO: {
- local $TODO = 'There seems to be no way around that much wizardry... which is ok';
- ok ($artist->is_column_changed ('rank'), 'Column marked as dirty on out-of-sync set_column value');
- }
- is ($artist->rank, '8', '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';
+# test in-memory operations
+for my $artist_maker (
+ sub { $schema->resultset('Artist')->new({ rank => 42 }) },
+ sub { my $art = $schema->resultset('Artist')->new({}); $art->rank(42); $art },
+) {
+
+ my $expected_from = $from_storage_ran;
+ my $expected_to = $to_storage_ran;
+
+ my $artist = $artist_maker->();
+
+ is $from_storage_ran, $expected_from, 'from has not run yet';
+ is $to_storage_ran, $expected_to, 'to has not run yet';
+
+ ok( ! $artist->has_column_loaded('artistid'), 'pk not loaded' );
+ ok( $artist->has_column_loaded('rank'), 'Filtered column marked as loaded under new' );
+ is( $artist->rank, 42, 'Proper unfiltered value' );
+ is( $artist->get_column('rank'), 21, 'Proper filtered value' );
+}
+
+# test literals
+for my $v ( \ '16', \[ '?', '16' ] ) {
+ my $art = $schema->resultset('Artist')->new({ rank => 10 });
+ $art->rank($v);
+
+ is_deeply( $art->rank, $v);
+ is_deeply( $art->get_filtered_column("rank"), $v);
+ is_deeply( $art->get_column("rank"), $v);
+
+ $art->insert;
+ $art->discard_changes;
+
+ is ($art->get_column("rank"), 16, "Literal inserted into database properly");
+ is ($art->rank, 32, "filtering still works");
+
+ $art->update({ rank => $v });
+
+ is_deeply( $art->rank, $v);
+ is_deeply( $art->get_filtered_column("rank"), $v);
+ is_deeply( $art->get_column("rank"), $v);
+
+ $art->discard_changes;
+
+ is ($art->get_column("rank"), 16, "Literal inserted into database properly");
+ is ($art->rank, 32, "filtering still works");
}
IC_DIE: {
- dies_ok {
+ throws_ok {
DBICTest::Schema::Artist->inflate_column(rank =>
{ inflate => sub {}, deflate => sub {} }
);
- } q(Can't inflate column after filter column);
+ } qr/InflateColumn can not be used on a column with a declared FilterColumn filter/, q(Can't inflate column after filter column);
DBICTest::Schema::Artist->inflate_column(name =>
{ inflate => sub {}, deflate => sub {} }
);
- dies_ok {
+ throws_ok {
DBICTest::Schema::Artist->filter_column(name => {
filter_to_storage => sub {},
filter_from_storage => sub {}
});
- } q(Can't filter column after inflate column);
+ } qr/FilterColumn can not be used on a column with a declared InflateColumn inflator/, 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() if DBIx::Class::_ENV_::OLD_MRO;
+
+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() if DBIx::Class::_ENV_::OLD_MRO;
+
+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;