[Dbix-class] something strange with Class::Accessor::Fast and DBIx::Class

Brandon Black blblack at gmail.com
Thu May 24 23:44:09 GMT 2007


On 5/24/07, stephen joseph butler <stephen.butler at gmail.com> wrote:
> I'm seeing something strange with Class::Accessor::Fast, DBIx::Class,
> and one of my classes. Here's a basic test case:
>
> https://netfiles.uiuc.edu/sbutler1/www/C3Test.tar.gz
>
> When I run ./scripts/c3test.pl, I get:
>
> Subroutine new redefined at /home/me/C3Test/lib/C3Test.pl line 16.
>
> Anyone know what I'm doing wrong? Here's the versions of the various
> packages involved:
>
> Class::Accessor - 0.30
> Class::C3 - 0.18
> Class::C3::XS - 0.06
> DBIx::Class - 0.07006
>

Yes, this is really weird, but unfortunately expected, behavior.  This
is a good example of two of the fundamentally ugly things about
Class::C3 that were unavoidable in pure perl but fixed in the 5.9.5
implementation.  (1) That an explicit runtime initialize() method is
needed, and (2) That inheritance is fixed up by "caching" superclass
subroutines directly into subclasses as if they were local methods.

What's going on here, at compile time, line by line in C3Test.pm:

-------------
package C3Test;

use strict;
use warnings;
use base qw/Class::Accessor::Fast/;
# ^^ C::A::F inherits new() from C::A, and so do you.

use Class::C3;
# ^^ This adds C3Test to a list of classes Class::C3 needs to initialize later
use C3Test::Schema;
# ^^ DBIx::Class uses Class::C3 also, and calls
Class::C3::initialize() when you do load_classes()
#      Class::C3::initialize() aliases Class::Accessor::new into your
package as C3Test::new

sub new {
# ^^ Now you're supplying your own local new(), which redefines the
one Class::C3 put here
---------------

One way around the warning is to swap your two use lines, so that the
schema gets set up before you "use Class::C3" in your own class.  You
need to call Class::C3::initialize at some point to get your own C3
stuff working too.  If you arrange everything just right in a begin
block, you can avoid re-initializing the DBIC stuff twice, like:

BEGIN {
    no warnings 'redefine'; # for the "local" below
    use Class::C3;
    local *Class::C3::initialize = sub { };
    require C3Test::Schema;
}

Now DBIC's classes and your own are on C3's initialization list, but
none have been initialized yet.  You'll need to do this at runtime at
some point that's appropriate for your app.

-- Brandon



More information about the Dbix-class mailing list