From: Justin Hunter Date: Mon, 28 Feb 2011 23:28:53 +0000 (-0800) Subject: Switch cursor accessor to CAG's component_class type for autoloading X-Git-Tag: v0.08191~71 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=db29433c74a98967f61f117bd508c06055db2892;p=dbsrgits%2FDBIx-Class.git Switch cursor accessor to CAG's component_class type for autoloading --- diff --git a/Changes b/Changes index d18dea6..53da767 100644 --- a/Changes +++ b/Changes @@ -21,6 +21,8 @@ Revision history for DBIx::Class when deploying a schema via sql file - Fix reverse_relationship_info on prototypical result sources (sources not yet registered with a schema) + - Automatically require the requested cursor class before use + (RT#64795) * Misc - Only load Class::C3 and friends if necessary ($] < 5.010) diff --git a/lib/DBIx/Class.pm b/lib/DBIx/Class.pm index e6cc6a7..86bc9b0 100644 --- a/lib/DBIx/Class.pm +++ b/lib/DBIx/Class.pm @@ -19,7 +19,7 @@ use mro 'c3'; use DBIx::Class::Optional::Dependencies; use vars qw($VERSION); -use base qw/DBIx::Class::Componentised Class::Accessor::Grouped/; +use base qw/DBIx::Class::Componentised DBIx::Class::AccessorGroup/; use DBIx::Class::StartupCheck; sub mk_classdata { diff --git a/lib/DBIx/Class/AccessorGroup.pm b/lib/DBIx/Class/AccessorGroup.pm index 4d7e046..bd245e3 100644 --- a/lib/DBIx/Class/AccessorGroup.pm +++ b/lib/DBIx/Class/AccessorGroup.pm @@ -5,6 +5,21 @@ use warnings; use base qw/Class::Accessor::Grouped/; +our %successfully_loaded_components; + +sub get_component_class { + my $class = $_[0]->get_inherited($_[1]); + if (defined $class and ! $successfully_loaded_components{$class}) { + $_[0]->ensure_class_loaded($class); + $successfully_loaded_components{$class}++; # only increment if the load succeeded + } + $class; +}; + +sub set_component_class { + shift->set_inherited(@_); +} + 1; =head1 NAME diff --git a/lib/DBIx/Class/Storage.pm b/lib/DBIx/Class/Storage.pm index edfef85..dcc68bc 100644 --- a/lib/DBIx/Class/Storage.pm +++ b/lib/DBIx/Class/Storage.pm @@ -13,7 +13,7 @@ use Try::Tiny; use namespace::clean; __PACKAGE__->mk_group_accessors('simple' => qw/debug schema/); -__PACKAGE__->mk_group_accessors('inherited' => 'cursor_class'); +__PACKAGE__->mk_group_accessors('component_class' => 'cursor_class'); __PACKAGE__->cursor_class('DBIx::Class::Cursor'); diff --git a/t/04_c3_mro.t b/t/04_c3_mro.t index 3224b5b..0c22bab 100644 --- a/t/04_c3_mro.t +++ b/t/04_c3_mro.t @@ -51,6 +51,7 @@ is_deeply ( DBIx::Class DBIx::Class::Componentised Class::C3::Componentised + DBIx::Class::AccessorGroup Class::Accessor::Grouped /], 'Correctly ordered ISA of DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server' diff --git a/t/39load_namespaces_stress.t b/t/39load_namespaces_stress.t new file mode 100644 index 0000000..db178ee --- /dev/null +++ b/t/39load_namespaces_stress.t @@ -0,0 +1,49 @@ +use strict; +use warnings; +use Test::More; +use Time::HiRes qw/gettimeofday/; + +use lib qw(t/lib); +use DBICTest; # do not remove even though it is not used + +our $src_count = 100; + +for (1 .. $src_count) { + eval <table($_); + __PACKAGE__->add_columns ( + id => { data_type => 'integer', is_auto_increment => 1 }, + data => { data_type => 'varchar', size => 255 }, + ); + __PACKAGE__->set_primary_key('id'); + __PACKAGE__->add_unique_constraint(['data']); + +EOM +} + +{ + package DBICTest::NS::Stress::Schema; + + use base qw/DBIx::Class::Schema/; + + sub _findallmod { + return $_[1] eq ( __PACKAGE__ . '::Result' ) + ? ( map { __PACKAGE__ . "::Result::T$_" } 1 .. $::src_count ) + : () + ; + } +} + +is (DBICTest::NS::Stress::Schema->sources, 0, 'Start with no sources'); + + +note gettimeofday . ":\tload_namespaces start"; +DBICTest::NS::Stress::Schema->load_namespaces; +note gettimeofday . ":\tload_namespaces finished"; + +is (DBICTest::NS::Stress::Schema->sources, $src_count, 'All sources attached'); + +done_testing; diff --git a/t/cdbi/has_many_loads_foreign_class.t b/t/cdbi/has_many_loads_foreign_class.t index e94a3ab..51cec5d 100644 --- a/t/cdbi/has_many_loads_foreign_class.t +++ b/t/cdbi/has_many_loads_foreign_class.t @@ -1,6 +1,6 @@ use strict; use Test::More; - +use Class::Inspector (); BEGIN { eval "use DBIx::Class::CDBICompat;"; diff --git a/t/lib/DBICTest/Cursor.pm b/t/lib/DBICTest/Cursor.pm new file mode 100644 index 0000000..7f8873f --- /dev/null +++ b/t/lib/DBICTest/Cursor.pm @@ -0,0 +1,7 @@ +package DBICTest::Cursor; + +use strict; +use warnings; +use base qw/DBIx::Class::Storage::DBI::Cursor/; + +1; diff --git a/t/resultset_class.t b/t/resultset_class.t index 5aa7a92..607c1f2 100644 --- a/t/resultset_class.t +++ b/t/resultset_class.t @@ -10,9 +10,12 @@ use DBICTest; is(DBICTest::Schema->source('Artist')->resultset_class, 'DBICTest::BaseResultSet', 'default resultset class'); ok(!Class::Inspector->loaded('DBICNSTest::ResultSet::A'), 'custom resultset class not loaded'); + DBICTest::Schema->source('Artist')->resultset_class('DBICNSTest::ResultSet::A'); -ok(Class::Inspector->loaded('DBICNSTest::ResultSet::A'), 'custom resultset class loaded automatically'); + +ok(!Class::Inspector->loaded('DBICNSTest::ResultSet::A'), 'custom resultset class not loaded on SET'); is(DBICTest::Schema->source('Artist')->resultset_class, 'DBICNSTest::ResultSet::A', 'custom resultset class set'); +ok(Class::Inspector->loaded('DBICNSTest::ResultSet::A'), 'custom resultset class loaded on GET'); my $schema = DBICTest->init_schema; my $resultset = $schema->resultset('Artist')->search; diff --git a/t/storage/cursor.t b/t/storage/cursor.t new file mode 100644 index 0000000..fb5f0cc --- /dev/null +++ b/t/storage/cursor.t @@ -0,0 +1,16 @@ +use strict; +use warnings; + +use Test::More; +use Test::Exception; + +use lib qw(t/lib); +use DBICTest; + +my $schema = DBICTest->init_schema(cursor_class => 'DBICTest::Cursor'); + +lives_ok { + is($schema->resultset("Artist")->search(), 3, "Three artists returned"); +} 'Custom cursor autoloaded'; + +done_testing; diff --git a/xt/podcoverage.t b/xt/podcoverage.t index 022e320..caaeca4 100644 --- a/xt/podcoverage.t +++ b/xt/podcoverage.t @@ -118,6 +118,7 @@ my $exceptions = { 'DBIx::Class::Admin::*' => { skip => 1 }, 'DBIx::Class::ClassResolver::PassThrough' => { skip => 1 }, 'DBIx::Class::Componentised' => { skip => 1 }, + 'DBIx::Class::AccessorGroup' => { skip => 1 }, 'DBIx::Class::Relationship::*' => { skip => 1 }, 'DBIx::Class::ResultSetProxy' => { skip => 1 }, 'DBIx::Class::ResultSourceProxy' => { skip => 1 },