使用带有 CODE 引用的 Apache::Session 存储 Moose 对象的替代方案

发布于 2024-09-06 07:43:26 字数 3113 浏览 9 评论 0原文

我有一个 Moose 类,我想使用 Apache::Session::File 来存储它。

但是,Apache::Session::File 默认情况下不会存储它,而是收到错误消息:

 (in cleanup) Can't store CODE items at blib\lib\Storable.pm (autosplit into blib\lib\auto\Storable\_freeze.al)...

规避此问题

$Storable::Deparse = 1;
$Storable::Eval = 1;

可以通过设置以允许序列化 CODE 引用来

。下面列出了 Moose 类中的违规方法,该方法从 mysql 数据库检索列:

sub _build_cell_generic {
    my ($self,$col) = @_;
    my $sth = $self->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
    $sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
    my $val = $sth->fetchrow_array;
    $sth->finish;
    return defined $val ? $val : undef;
}

因此,dbh 对象(即 DBIx::Connector)可能包含 CODE 引用。

为了允许序列化此 Moose 类,是否有比设置 $Storable::Deparse 和 $Storable::Eval 更好的替代方法?

以下测试脚本会产生错误:

#!/usr/bin/perl -w

use Apache::Session::File;
use Test::More;
use strict;
use warnings;

require_ok( 'GSM::TestCell' );
require_ok( 'GSM::SQLConnection');

my $db = new_ok('GSM::SQLConnection');
my $cell4 = new_ok( 'GSM::TestCell' => [{LAC => 406, CI => 24491, DB => $db }] );

my %session;
tie %session, 'Apache::Session::File', undef, {Directory =>"./", LockDirectory   => "./" };
print "BCCH is ",$cell4->BCCH,"\n";
$session{$cell4->ID} = $cell4;
done_testing();
__END__

SQL 连接类定义为:

package GSM::SQLConnection;
#use DBI;
use Moose;
use DBIx::Connector;

has dbixc => (is => 'ro', isa => 'DBIx::Connector', lazy_build => 1, handles => [ qw(dbh) ]); 

sub _build_dbixc {
    my $self = shift;
    my $dsn = 'DBI:mysql:testDB;host=127.0.0.1;port=3306';
    return DBIx::Connector->new($dsn,'user','pwd');
}

sub call_dbh {
    my $self = shift;
    my $method = shift;
    my @args = @_;
    $self->dbixc->run(fixup => sub { $_->$method(@args) });
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;

TestCell 类定义为:

package GSM::TestCell;
use MooseX::NaturalKey;
use strict;
use warnings;

has [qw(LAC CI)] => (is => 'ro', required => 1);
has [qw(ID BCCH IMPORTDATE)] => (is => 'rw', lazy_build => 1);
has 'DB' => (is => 'rw', isa => 'GSM::SQLConnection', required => 1, );
has 'TABLE' => (is => 'rw', default => 'Cell');

primary key =>('LAC','CI');

sub _build_ID {
    my $self = shift;
    return join(',',$self->LAC,$self->CI);
}

sub _build_IMPORTDATE {return '2010-06-21'}

sub _build_BCCH {(shift)->_build_cell_generic('BCCHFrequency');}

sub _build_cell_generic {
    my ($self,$col) = @_;
    my $sth = $self->DB->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
    $sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
    my $val = $sth->fetchrow_array;
    $sth->finish;
    return defined $val ? $val : undef;
}

no Moose;
__PACKAGE__->meta->make_immutable;
1;

I have a Moose class that i would like to store using Apache::Session::File.

However, Apache::Session::File by default will not store it and instead i get the error message:

 (in cleanup) Can't store CODE items at blib\lib\Storable.pm (autosplit into blib\lib\auto\Storable\_freeze.al)...

This problem can be circumvented by setting

$Storable::Deparse = 1;
$Storable::Eval = 1;

in order to allow CODE references to be serialized.

The offending method in the Moose class is listed below, which retrieves a column from a mysql database:

sub _build_cell_generic {
    my ($self,$col) = @_;
    my $sth = $self->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
    $sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
    my $val = $sth->fetchrow_array;
    $sth->finish;
    return defined $val ? $val : undef;
}

So presumably the dbh object (isa DBIx::Connector) contains CODE references.

Is there a better alternative in order to allow serialization of this Moose class than setting $Storable::Deparse and $Storable::Eval ?

The following test script produces the error:

#!/usr/bin/perl -w

use Apache::Session::File;
use Test::More;
use strict;
use warnings;

require_ok( 'GSM::TestCell' );
require_ok( 'GSM::SQLConnection');

my $db = new_ok('GSM::SQLConnection');
my $cell4 = new_ok( 'GSM::TestCell' => [{LAC => 406, CI => 24491, DB => $db }] );

my %session;
tie %session, 'Apache::Session::File', undef, {Directory =>"./", LockDirectory   => "./" };
print "BCCH is ",$cell4->BCCH,"\n";
$session{$cell4->ID} = $cell4;
done_testing();
__END__

The SQL connection class is defined as:

package GSM::SQLConnection;
#use DBI;
use Moose;
use DBIx::Connector;

has dbixc => (is => 'ro', isa => 'DBIx::Connector', lazy_build => 1, handles => [ qw(dbh) ]); 

sub _build_dbixc {
    my $self = shift;
    my $dsn = 'DBI:mysql:testDB;host=127.0.0.1;port=3306';
    return DBIx::Connector->new($dsn,'user','pwd');
}

sub call_dbh {
    my $self = shift;
    my $method = shift;
    my @args = @_;
    $self->dbixc->run(fixup => sub { $_->$method(@args) });
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;

The TestCell class is defined as:

package GSM::TestCell;
use MooseX::NaturalKey;
use strict;
use warnings;

has [qw(LAC CI)] => (is => 'ro', required => 1);
has [qw(ID BCCH IMPORTDATE)] => (is => 'rw', lazy_build => 1);
has 'DB' => (is => 'rw', isa => 'GSM::SQLConnection', required => 1, );
has 'TABLE' => (is => 'rw', default => 'Cell');

primary key =>('LAC','CI');

sub _build_ID {
    my $self = shift;
    return join(',',$self->LAC,$self->CI);
}

sub _build_IMPORTDATE {return '2010-06-21'}

sub _build_BCCH {(shift)->_build_cell_generic('BCCHFrequency');}

sub _build_cell_generic {
    my ($self,$col) = @_;
    my $sth = $self->DB->call_dbh('prepare','select '.$col.' from '.$self->TABLE.' where CI = ? and LAC = ? and IMPORTDATE = ?');
    $sth->execute($self->CI,$self->LAC,$self->IMPORTDATE);
    my $val = $sth->fetchrow_array;
    $sth->finish;
    return defined $val ? $val : undef;
}

no Moose;
__PACKAGE__->meta->make_immutable;
1;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

安稳善良 2024-09-13 07:43:26

我真的怀疑你真的需要序列化代码引用;您所包含的示例没有任何内容。无论如何,您不想序列化 DBIx::Connector 对象,因为它们仅特定于当前运行时实例。

DBIx::Connector 对象中可能有一个小的 coderef,因为通常将对 dbh 的访问包装在子中以捕获 文档

Moose 对象的序列化由 MooseX::Storable 处理,易于扩展。您可以在那里自定义序列化器以满足您的需求 - 即选择要序列化的属性和要忽略的属性。

I really doubt you really need to serialize code references; the example you included doesn't have any. You don't want to be serializing DBIx::Connector objects anyway, as they are only specific to the current runtime instance.

DBIx::Connector objects may have a small coderef in them, as it is common to wrap access to the dbh in a sub to catch cases where the connection goes away (see the discussion of 'fixup') in the documentation.

Serialization of Moose objects is handled by MooseX::Storable, which is easily extendable. You could customize a serializer in there to fit your needs - i.e. select which attributes to serialize and which to ignore.

坠似风落 2024-09-13 07:43:26

Apache::Session::File 使用的 Storable 类的文档使用 $Storable::Deparse 和 $Storable::Eval,但还建议了一种在“安全”中序列化 CODE 引用和反序列化的方法。 '隔间。本页的示例部分给出了一个示例:

http://perldoc.perl。 org/Storable.html#代码参考

The documentation for the Storable class, which is used by Apache::Session::File uses $Storable::Deparse and $Storable::Eval, but also goes on to suggest a method for serialization of CODE references and deserialization in a 'safe' compartment. An example is given in the Examples section of this page:

http://perldoc.perl.org/Storable.html#CODE-REFERENCES

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文