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

I'm a newb with Moose. I have the following perl script which creates an FFMech object:

#!/usr/bin/perl BEGIN { unshift @INC, "/home/steve/perl/perl-lib" } use strict; use warnings; use FFMech; my $ffm = FFMech->new;

The code for the FFMech object is here:

package FFMech; use strict; use warnings; $ENV{'DISPLAY'} = ':0.0'; use X11::GUITest qw/SendKeys FindWindowLike ClickWindow SetEventSendDe +lay/; use Moose; extends 'WWW::Mechanize::Firefox'; has 'window_id' => ( is => 'ro', isa => 'Int', );

As you can see, the class doesn't do anything. That's because I can't get over the initial hump of initializing the object without getting the following error:

Failed to connect to , problem connecting to "localhost", port 4242: C +onnection refused at /usr/local/share/perl/5.20.2/MozRepl/Client.pm l +ine 144

The error is occurring because Firefox is not running. You can launch Firefox with something like:

my $mech->new(launch => 'firefox');

However, I'm at a loss as to how to pass these arguments to the constructor for the WWW::Mechanize::Firefox object.

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Passing arguments to WWW::Mechanize::Firefox constructor with Moose
by nysus (Parson) on Mar 10, 2016 at 15:11 UTC

    Apparently it's as easy as this:

    my $ffm = FFMech->new(launch => 'firefox');

    How does Moose know to pass that argument to WWW::Mechanize::Firefox and not some other object that FFMech might extend?

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
    $nysus = $PM . $MCF;
    Click here if you love Perl Monks

Re: Passing arguments to WWW::Mechanize::Firefox constructor with Moose
by nysus (Parson) on Mar 11, 2016 at 07:44 UTC

      G'day nysus,

      "OK, I just learned that when extending non-Moose modules, you should use the MooseX::NonMoose package."

      I did this a few years back; these two articles were extremely helpful:

      1. Subclassing Tricky Non-Moose Classes: Don't Do It
      2. Subclassing Tricky Non-Moose Classes: Constructor Problems

      I used the information in those blogs to code Anomaly (a personal, unpublished module), which extends Exception::Class::Base. This module is complete and working; it has examples of code that will cover much of what you might need, such as BUILDARGS & FOREIGNBUILDARGS, and uses MooseX::ClassAttribute.

      package Anomaly v0.0.1; use 5.12.0; use Moose; use MooseX::ClassAttribute; use MooseX::NonMoose; extends qw(Exception::Class::Base); use namespace::autoclean; class_has generic_description => ( is => q{ro}, isa => q{Str}, default => q{Generic Anomaly}, ); around BUILDARGS => sub { my ($rc_constructor, $proto, @args) = @_; my $class = ref $proto || $proto; if (@args % 2) { push @args, q{message}; } return $class->$rc_constructor(@args); }; sub FOREIGNBUILDARGS { my ($proto, @args) = @_; my $class = ref $proto || $proto; my %wanted = (); if (@args % 2) { $wanted{message} = shift @args; } my %remaining = (@args); my %translation = (msg => q{message}); for my $key ($class->meta->get_attribute_list()) { if (exists $remaining{$key}) { if (exists $translation{$key}) { $wanted{$translation{$key}} = $remaining{$key}; } delete $remaining{$key}; } } if (exists $remaining{error}) { if (! exists $wanted{message}) { $wanted{message} = $remaining{error}; } delete $remaining{error}; } return (%wanted, %remaining); } has description => ( is => q{rw}, isa => q{Str}, default => sub { __PACKAGE__->generic_description() }, ); has detail => ( is => q{ro}, isa => q{Str}, default => q{}, ); has additional_info => ( is => q{ro}, isa => q{ArrayRef[HashRef]}, default => sub { [] }, lazy => 1, required => 0, ); sub add_additional_info { my ($self, $rh_new_info) = @_; my $ra_current_info = $self->additional_info(); push @$ra_current_info, $rh_new_info; $self->additional_info($ra_current_info); return; } no Exception::Class::Base; no MooseX::NonMoose; no MooseX::ClassAttribute; no Moose; __PACKAGE__->meta->make_immutable; 1;

      — Ken

        OK, wow, thanks for the links and sample code. I will definitely study these closely.

        While I have you ear right now, what if I want to override a method in the parent class (WWW::Firefox::Mechanize)? Is delegating, as shown in your first link, still the best option? Here's some code pseudocode to try to convey what I mean:

        use WWW::Mechanize::Firefox; has 'bot' => ( is => 'ro', isa => 'WWW::Mechanize::Firefox', ); sub get { my ($self, $url) = @_; $self->bot->get($url, synchronize => 1); }

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
        $nysus = $PM . $MCF;
        Click here if you love Perl Monks

      OK, I just learned that when extending non-Moose modules, you should use the MooseX::NonMoose package.

      Moose must be fantastic :D

Re: Passing arguments to WWW::Mechanize::Firefox constructor with Moose
by nysus (Parson) on Mar 11, 2016 at 16:37 UTC

    For those who are interested in this problem, here is some code I used to solve this problem. I offer no guarantees that this is the best approach but it works the way I want it to. Note that this code introduces an intermediary class, EventRepository, that was not mentioned in the OP. I left out this class to keep the OP simple.

    use EventRepository; my $er = EventRepository->new(launch => 'firefox', activate => 1); $er->get('http://google.com');

    Here is the EventRepository class with an method overriding the parent class, FFMech:

    use Moose; extends 'FFMech'; sub get { my ($self, $url) = @_; $self->SUPER::get($url, synchronize => 0); }

    And here is the FFMech class which extends WWW::Mechanize::Firefox and is used to basically prep the Firefox window for use by X11::GUITest:

    $ENV{'DISPLAY'} = ':0.0'; #allows script to run when called from remot +e terminal window use X11::GUITest qw/SendKeys FindWindowLike ClickWindow SetEventSendDe +lay/; use Moose; use MooseX::NonMoose; extends 'WWW::Mechanize::Firefox'; has 'window_id' => ( is => 'rw', isa => 'Int', ); sub BUILD { my $self = shift; $self->window_id(FindWindowLike('Mozilla Firefox')); ClickWindow($self->window_id); }

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
    $nysus = $PM . $MCF;
    Click here if you love Perl Monks