Search code examples
perlmoose

How can I flexibly add data to Moose objects?


I'm writing a module for a moose object. I would like to allow a user using this object (or myself...) add some fields on the fly as he/she desires. I can't define these fields a priori since I simply don't know what they will be.

I currently simply added a single field called extra of type hashref which is is set to rw, so users can simply put stuff in that hash:

# $obj is a ref to my Moose object    
$obj->extra()->{new_thingie}="abc123"; # adds some arbitrary stuff to the object
say $obj->extra()->{new_thingie};

This works. But... is this a common practice? Any other (possibly more elegant) ideas?

Note I do not wish to create another module the extends this one, this really just for on-the-fly stuff I'd like to add.


Solution

  • I would probably do this via native traits:

    has custom_fields => (
        traits     => [qw( Hash )],
        isa        => 'HashRef',
        builder    => '_build_custom_fields',
        handles    => {
            custom_field         => 'accessor',
            has_custom_field     => 'exists',
            custom_fields        => 'keys',
            has_custom_fields    => 'count',
            delete_custom_field  => 'delete',
        },
    );
    
    sub _build_custom_fields { {} }
    

    On an object you'd use this like the following:

    my $val = $obj->custom_field('foo');           # get field value
    $obj->custom_field('foo', 23);                 # set field to value
    
    $obj->has_custom_field('foo');                 # does a specific field exist?
    $obj->has_custom_fields;                       # are there any fields?
    
    my @names = $obj->custom_fields;               # what fields are there?
    my $value = $obj->delete_custom_field('foo');  # remove field value
    

    A common use-case for stuff like this is adding optional introspectable data to exception and message classes.