Moose Perl:“修改所有子类中的多个方法”

时间:2012-08-15 09:47:19

标签: perl methods moose method-modifier

我有一个Moose BaseDBModel,它有不同的子类映射到数据库中的表。子类中的所有方法都类似于“get_xxx”或“update_xxx”,它指的是不同的数据库操作。

现在我想为所有这些方法实现一个缓存系统,所以我的想法是“之前”所有名为“get_xxx”的方法,我将搜索方法的名称作为我的memcache池中的键值。如果我找到了值,那么我将直接返回值而不是方法。

理想情况下,我的代码就像这样

BaseDBModel

package Speed::Module::BaseDBModel;
use Moose;
sub BUILD {
  my $self = shift;

  for my $method ($self->meta->get_method_list()){
    if($method =~ /^get_/){
      $self->meta->add_before_method_modifier($method,sub {
        warn $method;
        find_value_by_method_name($method);
        [return_value_if_found_value]
      });
    }
  }
}

子类示例1

package Speed::Module::Character;
use Moose;

extends 'Speed::Module::BaseDBModel';
method get_character_by_id {
    xxxx
}

现在我的问题是,当我的程序运行时,它会反复修改方法,例如:

  1. 重启apache

  2. 访问将调用get_character_by_id的页面,这样我就可以看到一条警告消息

  3. 代码:

    my $db_character = Speed::Module::Character->new(glr => $self->glr);
    $character_state = $db_character->get_character_by_id($cid);
    

    警告:

    get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
    

    但是如果我刷新页面,我看到了2条警告信息

    警告:

    get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
    get_character_by_id at /Users/dyk/Sites/speed/lib/Speed/Module/BaseDBModel.pm line 60.
    

    我正在使用带有apache的mod_perl 2.0,每次刷新页面时,我的get_character_by_id方法都会被修改,我不想要

2 个答案:

答案 0 :(得分:0)

每次构建新实例时,你的BUILD是不是在执行add_before?我不确定那是你想要的。


嗯,简单/笨重的方法是设置一些包级别标志,这样你只需要做一次。

否则,我想你想要加入Moose自己的属性构建。看看这个:http://www.perlmonks.org/?node_id=948231

答案 1 :(得分:0)

问题是BUILD每次创建对象时都会运行(即每次->new()次调用后),但add_before_method_modifier会将修饰符添加到,即所有对象

简单解决方案

请注意,每次use调用import来自已使用过的包。那是你想要添加修饰符的地方。

父:

package Parent;

use Moose;

sub import {
    my ($class) = @_;

    foreach my $method ($class->meta->get_method_list) {
        if ($method =~ /^get_/) {
            $class->meta->add_before_method_modifier($method, sub {
                warn $method
            });
        }
    }
}

1;

Child1:

package Child1;

use Moose;
extends 'Parent';

sub get_a { 'a' }

1;

CHILD2:

package Child2;

use Moose;
extends 'Parent';

sub get_b { 'b' }

1;

所以现在它按预期工作:

$ perl -e 'use Child1; use Child2; Child1->new->get_a; Child2->new->get_b; Child1->new->get_a;'
get_a at Parent.pm line 11.
get_b at Parent.pm line 11.
get_a at Parent.pm line 11.

清洁剂解决方案

由于您无法100%确定将import被调用(因为您无法确定将使用use)更简洁明了的解决方案只需添加类似{{{ 1}}在每个派生类中。

use My::Getter::Cacher

在这种情况下,每个派生类都应包含package My::Getter::Cacher; sub import { my $class = [caller]->[0]; # ... } extends 'Parent',因为第一行是关于继承,而第二行是关于在修饰符之前添加。你可能会认为它有点多余,但正如我所说,我相信它更清洁,更直接。

P上。 S上。

也许你应该看一下Memoize模块。