Class::Trait INIT block

Ovid on 2007-05-31T16:00:37

I've gotten a couple of emails from folks about the annoying "too late to run INIT block" error which comes up when using Class::Trait. Due to how Perl works, there's not much which can be done about it, but here's one way I've dealt with it in my Test::Class base class:

sub startup : Test(startup) {
    my $test = shift;

    # If there are any tests in this class using the db, set it up:
    if($test->_pkg_has_attribute('DB')) { 
        $test->_database( TEST::Database->new );
    } 

    { 
        my $using_traits = 0;

        # Because of how traits work, they need to be loaded at compile time
        # or else their integrity checks fail.  This skips their warning and
        # runs the integrity checks manually if traits are used.
        local $SIG{__WARN__} = sub {
            my $warning = shift;
            if ( $warning =~ /Too late to run INIT block.*Class\/Trait.pm/ ) { 
                $using_traits = 1;
                return;
            } 
            CORE::warn($warning);
        };
        my $class = $test->_class;
        $class->require or $test->FAIL_ALL("Could not require $class: $@");
        Class::Trait->initialize if $using_traits;
    } 
}