tags:

views:

45

answers:

1

Following phaylon's answer to "How can I flexibly add data to Moose objects?", suppose I have the following Moose attribute:

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 { {} }

Now, suppose I'd like to croak if trying to read (but not write) to a non-existing custom field. I was suggested by phaylon to wrap custom_field with an around modifier. I have experimented with around modifiers following the various examples in Moose docs, but couldn't figure how to modify a handle (rather than just an object method).

Alternatively, is there another way to implement this croak-if-try-to-read-nonexisting-key?

+5  A: 

They're still just methods generated by Moose. You can just do:

around 'custom_field' => sub {
    my $orig  = shift;
    my $self  = shift;
    my $field = shift;

    confess "No $field" unless @_ or $self->has_custom_field($field);

    $self->$orig($field, @_);
};

(croak is not very useful in method modifiers at the moment. It will just point you at internal Moose code.)

In fact, you don't need to use around for this. Using before is simpler:

before 'custom_field' => sub {
    my $self  = shift;
    my $field = shift;

    confess "No $field" unless @_ or $self->has_custom_field($field);
};
cjm
@David B, `handles` is creating standard object methods. An object can't have two methods with the same name. How would it know which one you were calling? (Perl 5 doesn't have multimethods.)
cjm
+1 Thank you cjm. I was trying to edit my comment to which you replied, but deleted it accidentally. Just for the record, I was asking something like 'what happens if two attributes have a handle with the same name'. Apparently that's impossible. Thanks again!
David B
@David just to clarify, the `handles` option is meant to be read as the verb 'handles', not the noun 'handles'. As in "this attribute *handles* these methods", not "this attribute has these handles". It's a delegation tool.
hobbs
@hobbs Thanks for clarifying, that makes sense.
David B