in reply to Moose: Where to define a method required by an attribute trait?

I think perhaps you want something that ends up looking more like this:

has testdir => ( traits => ['DirOption'], isa => 'Str', is => 'rw', rootdir => '/home/paulatreides', );
You can read the Moose::Manual entry on attribute traits to see how that is accomplished, it is fairly straightforward and common use of attribute traits (to add more options to has).

As for your _build_rootdir approach, you could use MooseX::Role::Parameterized for this. In that case it will look more like this instead

has testdir => ( traits => [ 'DirOption' => { rootdir => '/home/paulatreides' } + ], isa => 'Str', is => 'rw', );
This is a less common way to use attribute traits, but it too should work.

-stvn

Replies are listed 'Best First'.
Re^2: Moose: Where to define a method required by an attribute trait?
by maxhq (Novice) on Apr 29, 2010 at 09:10 UTC

    Thank you very much for your hint on how to give a parameter to an attribute trait! I did not find an example anywhere in the docs of MooseX::Role::Parameterized.

    Now I see that this also does not solve my problem, I am sorry that I forgot an important fact: The value given to the trait is no constant, so it has to be a kind of lazy builder.

    So more precisely, I need give an instance value to the trait, something like:

    has rootdir => ( isa => 'Str', is => 'rw', ); has testdir => ( traits => ['DirOption'], isa => 'Str', is => 'rw', rootdir => $self->rootDir, );
    Is this possible?

    -maxhq

      I am not sure why you are using attribute traits in the first place? Seems like you could do this with just plain old vanilla Moose. What do attribute traits give you that using cascading lazy builders would not?

      -stvn

        My real code is quite longer/different, so I thought it would be better to post an example here.

        My reasons: I found myself typing too much code each time I needed a special configuration class that represents a text config file and has functions to parse, validate (and in reverse also serialize) config entries.

        So the idea was to define different config entry types ("file", "ip address", "email address") as traits containing a parser and a serializer function.
        In the class representing the config file then I will only have to enrich the attributes with my traits to have a project specific config parser/writer:

        has alarmMailsTo => ( traits => ['ConfigEmail'], # trait for type "email" conf_key => 'ALARM_MAILS_TO' # associate with a config key isa => 'ArrayRef[Str]', is => 'rw', );

        A problem occurs when a trait needs some runtime information in it's parser/validator method. The problem and the workaround I have found by now is as follows:

        Class that represents config file

        .. with My::Config; ## some runtime information, eventually for the trait's method has validDomain => ( isa => 'Str', is => 'rw', ); has alarmMailsTo => ( traits => ['ConfigEmail'], conf_key => 'ALARM_MAILS_TO' attr_valid_domain => 'validDomain' ## give attr name to trait isa => 'ArrayRef[Str]', is => 'rw', ); ..

        Class role

        .. role My::Config { method load() { .. ## $attr is a Moose::Meta::Attribute $attr->parse($self, $configString); .. } .. }

        Attribute Trait

        .. role My::Config::ConfigEmail { has attr_valid_domain => ( isa => 'Str', is => 'rw', required => 1, ); method parse($instance!, $value!) { .. $instance ->meta ->find_attribute_by_name($self->attr_valid_domain) ->get_value($instance); .. } .. }

        (Btw. I actually have a "base trait" that contains the parse() method and all "type traits" consume it)

        It works, but passing an attribute name to the trait and then passing an instance around seems not very elegant to me. Is there any other way to access the class instance from within an attribute trait method?

        Thanks a lot for your help so far...
        -maxhq