如何在Mojolicious模型中访问会话数据

时间:2015-07-29 04:07:57

标签: perl mojolicious

以下是Mojolicious(6.14)应用程序的示例...对于$ _ [0]和其他不太好的做法感到抱歉;我试着让它紧凑。

package ScopeTest;
use Mojo::Base 'Mojolicious';

sub startup {
  my $app = shift;

  $app->helper( hello    => sub { "Hello!" } );
  $app->helper( username => sub { $_[0]->session('username'); } );
  $app->helper( model    => sub { ScopeTest::Model->new( app => $_[0]->app ) } );
  $app->helper( hasPerm  => sub { $_[0]->model->hasPerm( @_ ) } );

  $app->routes->get('/alice')->to('controller#alice');
  $app->routes->get('/carol')->to('controller#carol');
  $app->routes->get('/steve')->to('controller#steve');
}

##############################
package ScopeTest::Controller;
use Mojo::Base 'Mojolicious::Controller';

sub alice { $_[0]->session( username => "alice" ); $_[0]->render_message() }
sub carol { $_[0]->session( username => "carol" ); $_[0]->render_message() }
sub steve { $_[0]->session( username => "steve" ); $_[0]->render( text =>
    sprintf "%s: %s\n", $_[0]->username, $_[0]->model->update_db ? 'Okay' : 'Fail' ) }

sub render_message { $_[0]->render( text =>
    sprintf "%s: %s\n", $_[0]->username, $_[0]->hasPerm('canLogin') ? 'Okay' : 'Fail' ) }

##############################
package ScopeTest::Model;
use Mojo::Base -base;

has 'app';

my %perms = ( alice => [ qw{ canLogin } ],
              carol => [ ],
              steve => [ qw{ canUpdateDB } ] );

sub hasPerm {
    my ( $self, $perm ) = @_;
    no warnings 'uninitialized';

    $self->app->log->debug("app->hello            = " . $self->app->hello                 );   # OKAY
    $self->app->log->debug("app->username         = " . $self->app->username              );   # FAILS
    $self->app->log->debug("session('username')   = " . $self->app->session('username')   );   # FAILS
    $self->app->log->debug("session->{'username'} = " . $self->app->session->{'username'} );   # FAILS

    my $username;   # = $self->app->username;
    return grep { $_ eq $perm } @{ $perms{$username} };
}

sub update_db {
    my ( $self, $data ) = @_;
    $self->hasPerm('canUpdateDB') or return;
    # else ...
    return 1;
}

1;

虽然$self->app->log->debug()$self->app->dumper()以及其他帮助者做了正确的事情,$self->app->session却没有。

我知道传递$app被认为不太理想,但我本以为上述至少要工作......

一遍又一遍地传递用户名(这是一个玩具示例;真正的应用程序有几十种不同的方法,有时相互调用等等)是否有更简洁的方法从模型类中访问会话数据?

PS - 在您说Model->new(username => $self->session('username')之前,这意味着知道,先验,我将需要哪些会话变量,并在构造函数和属性列表中枚举它们;我希望如果我只是通过整个$app(甚至是$app->session),我可以保持未来的发展。

谢谢!

1 个答案:

答案 0 :(得分:1)

我犯的错误是:“会话”信息与App无关;它与控制器相关联:

data<-data.frame(id=c("11_22", "11_22_bb", "11_22_bb_33", 
                       "22_bb_33", "bb_33", "ab_cc_sd", "dd_e3_bb", 
                       "33_34_sd_22_32_87_cc"), stringsAsFactors=FALSE)
data$len_char <- nchar(data$id)
data <- data[ order(data$len_char, decreasing=TRUE),]
data$flag <- TRUE

for( i in 2:nrow(data)){
    if( sum(grepl( data[i, "id"],
        data[ data$len_char > data$len_char[i] & data$flag, "id"])) > 0
       )
        data[i, "flag"] <- FALSE
}
data <- data[data$flag, ]
data

#                    id len_char flag
#8 33_34_sd_22_32_87_cc       20 TRUE
#3          11_22_bb_33       11 TRUE
#6             ab_cc_sd        8 TRUE
#7             dd_e3_bb        8 TRUE

然后:

$app->helper( model => sub { ScopeTest::Model->new( ctrl => $_[0] ) } );

是的,我知道将控制器传递给模型仍然不是最佳的,但这至少解释了为什么我无法让它在ALL之前工作......