Can I use an attribute modifer in Moose in a base class to handle multiple attributes from sub classes?

元气小坏坏 提交于 2019-12-23 03:24:19

问题


I've got several Modules that have a number of date time related attributes that accept a datestamp and return a human readable string ( dd Mon yyyy hh:mm:ss ).

package ModuleOne;

use Moose;

extends 'ModuleBase';

has date_attr_one => ( ... );

and then ...

package ModuleTwo;

use Moose;

extends 'ModuleBase';

has date_attr_mouse => ( ... );

As it's currently working I'm using an 'around' attribute modifier so that if there's no parameter return the a date in the format of '03 May 2012 12:33:42'. If there is a parameter in the format of '03 May 2012 12:33:42' the I want to set that as a datestamp.

So, in ModuleOne, there would be:

has date_attr_one => ( ... );

followed by:

around 'date_attr_one' => sub { ... }

Same type of thing occurs in the second module.

The problem I'm having is that there are multiple modules doing this and each of them is using the 'around' modifier and the same duplicated code. I'd like to move that around modifier into the base class so every Module that extends the base class can use that modifier. I tried putting it into the base class using a regex like: (in the base class)

around qr/date_attr_one/ => sub { ... }

I put some print statements in there that never executed. Roles don't allow such a thing.

Is there a way to move that around modifier into the base class so every Module that extends the base class can use that modifier where the attributes would have different names in each model?

So, as in the example above, the base class' around attribute modifier would need to handle $self->date_attr_one and $self->date_attr_mouse, among others.


回答1:


If you create a package like the one below, all you need in your classes is:

has date => (
   is     => 'rw',
   isa    => 'My::Date',
   coerce => 1,
);

Example code:

my $o = My::Class->new(date => '03 May 2012 12:33:42');
say $o->date();
say 0+$o->date();

$o->date(1336062822);
say $o->date();
say 0+$o->date();

The aforementioned module:

package My::Date;

use strict;
use warnings;

use Moose;
use Moose::Util::TypeConstraints;

use DateTime::Format::Strptime qw( );
use POSIX                      qw( strftime );

my $format = DateTime::Format::Strptime->new(
   pattern   => '%d %b %Y %H:%M:%S',
   locale    => 'en_US',
   time_zone => 'local',
   on_error  => 'croak',
);

has epoch => (
   is       => 'rw',
   isa      => 'Num',
   required => 1,
);

sub as_string {
   return strftime('%d %b %Y %H:%M:%S', localtime( $_[0]->epoch ));
}

coerce __PACKAGE__,
   from 'Num',
      via { __PACKAGE__->new( epoch => $_ ) },
   from 'Str',
      via { __PACKAGE__->new( epoch => $format->parse_datetime($_)->epoch ) };

use overload (
   '""' => sub { $_[0]->as_string },
   '0+' => sub { $_[0]->epoch },
   fallback => 1,
);

1;


来源:https://stackoverflow.com/questions/10506416/can-i-use-an-attribute-modifer-in-moose-in-a-base-class-to-handle-multiple-attri

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!