Skip Menu |

This queue is for tickets about the Moo CPAN distribution.

Report information
The Basics
Id: 101010
Status: resolved
Priority: 0/
Queue: Moo

People
Owner: Nobody in particular
Requestors: pecho [...] belwue.de
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 2.000000



Subject: around 'new' => sub{ ... } and class attributes are code position dependend
Date: Fri, 19 Dec 2014 14:50:49 +0100
To: bug-Moo [...] rt.cpan.org
From: Wolfgang Pecho <pecho [...] belwue.de>
Hi, perl 5.18.2 Moo: 1.006001 / 1.005000 if you do an "around 'new' " in Moo the object instantiation does not know attributes of the class, if the "attribute declaration" is given after the "around 'new' ". example code : -------------- package AroundNew; use strict; use warnings; use Moo; use MooX::StrictConstructor; has 'x_attr' => ( is => 'rw', required => 1, ); around 'new' => sub { my $orig = shift; my $self = shift; my $obj; eval { $obj = $self->$orig(@_); }; if ($@) { chomp($@); print "--> ERROR: AroundNew::new() died with '$@'\n"; exit; } return $obj; }; has 'y_attr' => ( is => 'rw', required => 1, ); 1; # in main #!/usr/bin/env perl use strict; use warnings; use AroundNew; print "--> Try to instantiate object \n"; my $an = AroundNew->new( x_attr => 1 , y_attr => 2 ); print "x_attr: ", $an->x_attr, "\n"; print "y_attr: ", $an->y_attr, "\n"; print "--> Done\n"; ------------- The output of main is: --> Try to instantiate object --> ERROR: AroundNew::new() died with 'Found unknown attribute(s) passed to the constructor: y_attr at (eval 23) line 57.' Message is from MooX::StrictConstructor, which is used here just to make the problem clear. If you debug into the $self->$orig code, you find in Method::Generate::Constructor: 53 # MooX::StrictConstructor 54==> my %attrs = ("x_attr" => 1,); 55: my @bad = sort grep { ! $attrs{$_} } keys %{ $args }; 56: if (@bad) { 57: die("Found unknown attribute(s) passed to the constructor: " . 58 join ", ", @bad); y_attr is missing. In the case you uncomment MooX::StrictConstructor you get the error: --> Try to instantiate object x_attr: 1 Use of uninitialized value in print at test_AroundNew.pl line 12. y_attr: --> Done And debugging shows in Method::Generate::Constructor 51==> my $new = bless({}, $class);; 52: if (exists $args->{"x_attr"}) { 53: $new->{"x_attr"} = $args->{"x_attr"}; 54 } 55: return $new; y_attr is missing. The code works if you put all attribute declarations above "around 'new' " which gives Method::Generate::Constructor 51: my $new = bless({}, $class);; 52: if (exists $args->{"x_attr"}) { 53: $new->{"x_attr"} = $args->{"x_attr"}; 54 } 55==> if (exists $args->{"y_attr"}) { 56: $new->{"y_attr"} = $args->{"y_attr"}; 57 } 58: return $new; or you replace Moo by Moose (i.e. Moo -> Moose, MooX::StrictConstructor -> MooseX::StrictConstructor). Hope there is a chance to fix it. Ciao Wolfgang
Using method modifiers on new isn't supported by Moo. There are some cases where this will work, but it's very fragile. BUILD and BUILDARGS are the supported mechanisms for customizing the constructor behavior. We should probably call this out in the documentation somewhere, and the code should warn about it failure modes.
Subject: Re: [rt.cpan.org #101010] around 'new' => sub{ ... } and class attributes are code position dependend
Date: Tue, 23 Dec 2014 14:22:49 +0100
To: bug-Moo [...] rt.cpan.org
From: Wolfgang Pecho <pecho [...] belwue.de>
Hi Graham, if Moo does not support 'around new' it should be documented and an exeception should be thrown. In our application we have a MainObject for a large application which is used by other modules and a CLI. We need a comprehensive error handling. In case of error at the instantiation of the MainObject we like to perform some actions ( like email notification ) and tried to avoid code repetition by using the 'around new' to handle it. Coming from Moose we expected it to work. For me the current behaviour of Moo is a clear bug which should be fixed. I hope developer/maintainer see a chance to get it in sync with Moose, it would be great. Thanks in advance Wolfgang On 12/21/2014 02:03 PM, Graham Knop via RT wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=101010 > > > Using method modifiers on new isn't supported by Moo. There are some cases where this will work, but it's very fragile. BUILD and BUILDARGS are the supported mechanisms for customizing the constructor behavior. > > We should probably call this out in the documentation somewhere, and the code should warn about it failure modes.
On 2014-12-23 05:23:06, pecho@belwue.de wrote: Show quoted text
> In our application we have a MainObject for a large application which > is > used by other modules and a CLI. > We need a comprehensive error handling. In case of error at the > instantiation of the MainObject > we like to perform some actions ( like email notification ) and tried > to avoid code repetition by using the 'around new' > to handle it. Coming from Moose we expected it to work.
"around new" is not supported in Moose either. If you have been using it without errors, you're just getting lucky, rather than using a valid and tested code path. The right place to put extra code that should run at construction time is in BUILDARGS (for pre-construction option validation) and in BUILD (for post-construction side effects).
Moo will now detect the failure cases of using around new, and throw an error. Fixed in 1.999_001.
Resolved in Moo 2.