develooper Front page | perl.moose | Postings from November 2015


Thread Next
Bill Moseley
November 21, 2015 20:07
Message ID:
I need a bit of help understanding this code in Catalyst used for adding in

            my $meta = Class::MOP::get_metaclass_by_name($class);
            $meta->superclasses($plugin, $meta->superclasses);

This is preventing BUILDARGS from running, and I'm not sure why.  Can
someone provide an explanation?


A Catalyst app extends 'Catalyst', and Catalyst extends Catalyst::Component.

A Catalyst Component has a config *class* attribute and it also has a
method.  BUILDARGS merges in the component's *class* configuration into the
instance arguments.

In other words, the component's class configuration can populate the
attributes each time the instance is created.

The issue I'm seeing is for (non Moose::Role) plugins the code above is
called and then BUILDARGS is no longer called and thus the config no longer
sets attributes.

The behavior of the app changes depending if loading non-Moose::Role
plugins or not.

So, I have three questions:

First, is is incorrect for Catalyst to use "sub BUILDARGS
instead of using the "around" method modifier?

Second, why is Catalyst::Component::BUILDARGS no longer called once

           $meta->superclasses($plugin, $meta->superclasses);

is run?   Is there some other BUILDARGS now overriding?

And third, I have included an example below of a Catalyst app that
demonstrates the behavior above. That app includes a "foo" attribute which
is initialized by the configuration.

Note that the "foo" attribute has "init_args => undef".

The "foo" attribute is initialized when the "MyPlugin" is commented out.

Why is "init_args => undef" not preventing "foo" from being initialized?

Here's a simple script that shows the behavior.


$ cat
package Catalyst::Plugin::MyPlugin;
use Moose;

package Foo;  # A Catalyst app.
use Moose;
extends 'Catalyst';
use Catalyst (
    'MyPlugin',   # <---- comment out to see change

has foo => (
    is  => 'ro',
    init_arg => undef,  # How is it that this attribute is ever set?

    foo => { some => 'hash' },


before dispatch => sub {
    my $self = shift;

    use Data::Dumper;

    *# Show what the value of the attribute is now.*
    *printf "attribute foo is [%s]\n", Dumper $self->foo;*

    die "dead\n";

package main;
use strict;
use warnings;
use Catalyst::Test 'Foo';

request '/hello';

Running with the MyPlugin I get:

attribute foo is [$VAR1 = undef;

Running w/o the plugin:

attribute foo is [$VAR1 = {
          'some' => 'hash'

What's also interesting is if I add this to the the Foo class then the
"foo" attribute is set even when the MyPlugin is included.

before BUILDARGS => sub {};

Bill Moseley

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About