Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re^5: Why does changing a Moose attributes' properties remove the around modifier

by mcrose (Beadle)
on Jul 18, 2011 at 21:17 UTC ( #915283=note: print w/replies, xml ) Need Help??


in reply to Re^4: Why does changing a Moose attributes' properties remove the around modifier
in thread Why does changing a Moose attributes' properties remove the around modifier

I use it for keeping objects internally with implicit error checking as anything uncoercible dies, but not exposing them externally. For a contrived example, something like:

has [ qw/server peer monitor netlog/ ] => ( is => 'ro', isa => 'NetAdd +r::IP', coerce => 1, required => 1 ); coerce 'NetAddr::IP' => from 'Str' => via { NetAddr::IP->new($_, '255. +255.255.255') }; around [ qw/server peer monitor netlog/ ] => sub { my $orig = shift; my $self = shift; my $netaddr_ip = $self->orig(@_); return $netaddr_ip->addr; };

The above accepds valid single IPs (v4 /32 and v6 /128) and passes them back out as addresses, but avoids the default stringification (CIDR notation) the object by default resolves to. Using the lists w/ around is shorter and easier to read as I don't need to make a seperate shim stub for each object's accessor and means it's less likely future refactoring will forget to stringify the accessor appropriately.

However, it's not possible to make a more specific derived class instance with default IPs for some values as it kills the 'around' modifier.

I mean, it's easy enough to say that 'you get an object back, deal with it B)' but if I can inflate passed things to objects as they come in and deflate them back to strings as they go out, why not do it?

Edit:Actually, why not just add a 'decoerce' or 'deflate' or something to the accessor, a coderef that gets run against a value as the value is being returned? It'd allow a (deflate => sub { $_->clone }) to be applied to a DateTime accessor, for example, to make sure a end user doesn't ->add() to your internal value, etc, while not being spooky action at a distance; it's just another attribute of the accessor that can be changed or ignored or overridden by inheriting classes.

Replies are listed 'Best First'.
Re^6: Why does changing a Moose attributes' properties remove the around modifier
by ikegami (Pope) on Jul 18, 2011 at 21:56 UTC

    If you're trying to perform validation, why not just use the facility designed for that?

    use Moose::Util::TypeConstraints; subtype 'Net::IP::Address', as 'Str', where { NetAddr::IP->new($_, '255.255.255.255') }; no Moose::Util::TypeConstraints;
    has [ qw/server peer monitor netlog/ ] => ( is => 'ro', isa => 'Net::IP::Address', required => 1, );
Re^6: Why does changing a Moose attributes' properties remove the around modifier
by ikegami (Pope) on Jul 18, 2011 at 22:10 UTC

    If we suppose you have a good reason to store the IP address an object, then I still find your approach very poor. Don't try to change the behaviour of an existing getter; create a getter that has the behaviour your want.

    coerce 'NetAddr::IP' => from 'Str' => via { NetAddr::IP->new($_, '255.255.255.255') }; for my $field (qw( server peer monitor netlog )) { my $object = "${field}_object"; has $object => ( init_arg => $field, is => 'ro', isa => 'NetAddr::IP', coerce => 1, required => 1, handles => { $field => sub { $_[0]->$object->addr }, }, ); }

    This makes

    $o->server
    a shortcut for
    $o->server_object->addr

    The constructor takes

    C->new(server => ...)
    rather than
    C->new(server_object => ...)
    thanks to init_arg.

    Thanks to coerce => 1 and the coercion rule, both a NetAddr::IP object and a IP address in string form can be used as the value passed to the constructor.

      Yeah, that's a much better way of behaving. I'd missed the documentation that mentioned 'init_arg'. I do need to read through the Class::MOP stuff some time to make sure I'm not missing out on things like this. Thanks for the pointer.

        It's possible to do without init_arg (which I didn't know about for the longest time either), but it's less clear.

        for my $field (qw( server peer monitor netlog )) { my $object = "${field}_object"; has $field => ( reader => $object, isa => 'NetAddr::IP', coerce => 1, required => 1, handles => { $field => sub { $_[0]->$object->addr }, }, ); }
Re^6: Why does changing a Moose attributes' properties remove the around modifier
by stvn (Monsignor) on Jul 19, 2011 at 01:12 UTC

    So my first concern with this approach is that you are overriding the accessors and returning a value that is in conflict with the type declared in the attribute. This is just bound to confuse someone at some point.

    My second concern is that you are blocking access to the underlying NetAddr::IP objects via the normal and expected accessor methods. This means that if someone wants/needs to get at the NetAddr::IP objects they must use raw HASH access. Essentially your code is forcing someone to do something they very much should not do.

    I suggest you follow ikegami suggestion in Re^6: Why does changing a Moose attributes' properties remove the around modifier and use the 'handles' option to get the addr return value but still keep access to the underlying NetAddr::IP object if you ever need it.

    Actually, why not just add a 'decoerce' or 'deflate' or something to the accessor, a coderef that gets run against a value as the value is being returned? It'd allow a (deflate => sub { $_->clone }) to be applied to a DateTime accessor, for example, to make sure a end user doesn't ->add() to your internal value, etc, while not being spooky action at a distance; it's just another attribute of the accessor that can be changed or ignored or overridden by inheriting classes.

    This might make a good MooseX:: module, I suggest giving it a try (though I think 'deflate' is better then 'decoerce'). It is the policy of the Moose core to not add any feature that has not been successfully implemented and tested as a MooseX:: module, this helps us to avoid running into back-compat issues.

    -stvn

      I may look into trying to write it in some spare time, if only to learn some of the Class::MOP and Moose internals better. Thanks for your feedback.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://915283]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (7)
As of 2018-10-19 00:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When I need money for a bigger acquisition, I usually ...














    Results (106 votes). Check out past polls.

    Notices?