1

我正在使用WWW::Mechanize自动化基于 Web 的后台点击我需要做的事情是让我的测试电子商务订单进入我需要它们的状态来测试我对一个长的、多部分的特定部分所做的更改工作流程。要批量处理大量订单,我需要Home经常点击链接。为了缩短时间,我WWW::Mechanize在运行时像这样破解了一个方法(基于brian d foy在Mastering Perl中的一个示例):

{ # Shortcut to go back to the home page by calling $mech->go_home
  # I know I'll get a warning and do not want it!
  no warnings 'once';
  my $homeLink = $mech->find_link( text => 'Home' )->url_abs();
  $homeLink =~ s/system=0/system=1/;
  *WWW::Mechanize::go_home = sub {
    my ($self) = @_;
    return $self->get($homeLink);
  };
}

这很好用,并且不会伤害任何人,因为我使用它的脚本仅供我使用,而不是更大系统的一部分。

但是现在我想知道是否有可能实际上只告诉一个$mech具有此方法的对象,而另一个WWW::Mechanize可能稍后创建的对象(例如,做一些交叉引用而不混淆另一个具有活动会话的对象我的后台)不能使用这种方法。

我不确定这是否可能,因为如果我了解对象在 Perl 中的工作方式,->操作员会告诉它go_home在包中查找子例程WWW::Mechanize并将其$mech作为第一个参数传递给它。如果这种理解是错误的,请纠正我。

我通过添加一种仅让原始$mech对象使用该功能的硬编码检查来进行实验。

my $onlyThisMechMayAccessThisMethod = "$mech";
my $homeLink = $mech->find_link( text => 'Home' )->url_abs();
$homeLink =~ s/system=0/system=1/;
*WWW::Mechanize::go_home = sub {
  my ($self) = @_;
  return undef unless $self eq $onlyThisMechMayAccessThisMethod;
  return $self->get($homeLink);
};

由于"$mech"包含存储数据的地址(例如WWW::Mechanize=HASH(0x2fa25e8)),因此当以这种方式进行字符串化时,另一个对象看起来会有所不同。

然而,我不相信这是要走的路。所以我的问题是:有没有更好的方法只让WWW::Mechanize类的一个对象有这个方法?我也很高兴有关此代码的其他建议。

4

1 回答 1

5

这只是

$mech->follow_link(text => 'Home')

而且我认为它不够特别,不足以保证有自己的方法,或者需要限制在一个独家的对象俱乐部。

还值得注意的是,无需使用 typeglob 来在不同的包中声明子例程。例如,您只需要编写

sub WWW::Mechanize::go_home {
    my ($self) = @_;
    return $self->get($homeLink);
};

但一般的解决方案是子类化WWW::Mechanize并仅将那些您希望拥有新方法的对象声明为成员。


文件MyMechanize.pm

package MyMechanize;

use strict;
use warnings;

use parent 'WWW::Mechanize';

sub go_home {
  my $self = shift;
  my $homeLink = $self->find_link(text => 'Home')->url_abs;
  $homeLink =~ s/system=0/system=1/;
  return $self->get($homeLink);
}

1;

文件test.pl

use strict;
use warnings;

use MyMechanize;

my $mech = MyMechanize->new;
$mech->get('http://mydomain.com/path/to/site/page.html')
$mech->go_home;
于 2012-07-24T17:36:05.387 回答