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

Moose role BUILD question

by saintex (Scribe)
on Mar 23, 2011 at 16:26 UTC ( [id://895033]=perlquestion: print w/replies, xml ) Need Help??

saintex has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,
I have a problem with Moose::Role.

I would like to start a method defined in the class, that is called in the BUILD method of my role.

I simplified the code, just in order to esemplify the problem.
This is the code:
package Browser; our $VERSION=0.01; use Moose::Role; requires qw(cookieCreate cookieDelete navigation); sub BUILD { my $self = shift; $self->cookieCreate; }
And this is the package:
package MyPackage; use Moose; with 'Browser'; sub BUILD { my $self = shift; Browser->BUILD; # or super->BUILD ? } sub cookieCreate { my $self = shift; }
I have this error:
Can't locate object method "cookieCreate" via package "Browser" at ...

Replies are listed 'Best First'.
Re: Moose role BUILD question
by ikegami (Patriarch) on Mar 23, 2011 at 16:46 UTC
      Thank you!
      In this way it works!
Re: Moose role BUILD question
by stvn (Monsignor) on Mar 24, 2011 at 13:20 UTC

    Actually this code has a problem, if your class has a BUILD method in it, then the role method will never get consumed. ikegami's solution will fix it for you, but it bypasses the nice aspects that BUILD and the BUILDALL method that calls it.

    Instead I suggest the more common Moose idiom which is to use method-modifiers with roles and BUILD, so your Browser role would look more like:

    package Browser; our $VERSION=0.01; use Moose::Role; requires qw(cookieCreate cookieDelete navigation); sub BUILD {} after 'BUILD' => sub { my $self = shift; $self->cookieCreate; };
    This will then work with classes which do not have an existing BUILD (by installing the empty one in the role) and ones which have an existing BUILD (local class beats role in composition, but the after modifier will always get applied).

    -stvn
      I agree that your solution is more idiomatic and cleaner, but what features are bypassed by the method I posted?

        The real problem was more in the OPs code. By putting a BUILD method in his role, he would have run into an issue if he tried to compose it into a class which already had a BUILD, because the local class version of a method beats the role version of it. So actually it is not really that your version was bypassing so much as just not using Roles properly. Once a role is composed into a class, it really should be "forgotten" about since all the methods are basically already "copied" into the class.

        Additionally, the BUILD method is never really meant to be called by outside-of-Moose-internals code, it is meant to be called by BUILDALL and in a very specific order so that the object is initialized properly. This is all done within the context of inheritance, which is a Class specific thing. Roles do not inherit, which is why we have to do the weird tricks I showed above to hook into BUILD from a role. So while your solution will force the call to Browser::BUILD and it will happen during the BUILD of the consuming class, it is bypassing all that machinery. Currently, the result is the same, but since you are calling things usually only reserved for internals to call, there is a possibility (although very slim) that this might cause issues down the road.

        -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://895033]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-03-29 00:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found