2012-05-24 14 views
5

Aloha!Composizione di ruoli in una classe Moose non funzionante

Ho un ruolo che sono impegnato a definire in una classe Moose chiamata Authable che è essenzialmente composta in qualsiasi classe che potrebbe potenzialmente richiedere qualche forma di autenticazione in futuro; è un ruolo piuttosto semplice, ecco l'interezza:

package Trello::API::Roles::Authable; 

use Moose::Role; 

#authentication information 
has key => (
    is => "rw", 
    isa => "Str", 
); 

has token => (
    is => "rw", 
    isa => "Str", 
); 

1; 

Per una qualche ragione, quando tento di comporre in una classe con più istruzioni diverse, vale a dire, con "Trello :: API :: :: ruoli Authable "; o con "Ruoli :: Autable";

ho sempre ottenere questo stesso messaggio di errore: You can only consume roles, Roles::Authable is not a Moose role.

Qualsiasi idea del perché questo potrebbe accadere?

Modifica!

Solo una nota a margine, ho controllato la fonte reale per Moose :: ruolo, e ho visto questo bit:

unless ($meta && $meta->isa('Moose::Meta::Role')) { 
     require Moose; 
     Moose->throw_error("You can only consume roles, " 
       . $role->[0] 
       . " is not a Moose role"); 
    } 

Questo sembra essere dove l'errore è in corso, così sembra quasi che per qualche motivo , il ruolo che sto implementando non sta affermando che è un ruolo nel metaclass. Anche se potrei sbagliarmi! Qualsiasi aiuto sarebbe apprezzato.

Un'altra comoda modifica!

Bonus: contesto di codice in cui viene chiamata la routine con.

package Trello::API::Resource; 

use Moose; 
use URI::Escape; 
use LWP::UserAgent; 


with 'Roles::Authable'; 

che quando faccio questo, si sa in modo intelligente per cercare di consumare Ruoli/Authable.pm ma per qualsiasi motivo, non riesce proprio a funzionare!

+1

Cosa intendi per "più affermazioni diverse?" Stai facendo 'con 'Trello :: API :: Roles :: Authable'' o' with' Roles :: Authable '; '? Perché non sembra che tu abbia un ruolo con quest'ultimo nome. – friedo

+0

[stai usando 'Moose' o' Any :: Moose'?] (Http://blogs.perl.org/users/sawyer_x/2012/05/priorities-when-using-anymoose-and-what-mouse- people-should-do.html) –

+0

Quello che voglio dire è che ho provato più varianti differenti; a questo punto, il file che tenta di utilizzare il ruolo è Trello :: API :: Resource, quindi sembra riconoscere Roles :: Authable come Trello :: API :: Roles :: Authable e tenta di utilizzare quel modulo. A questo punto, non riconoscerà dove sono i moduli come non li ho messi nella reale strucutre della directory del modulo; Potrei sempre modificare @INC ma a questo punto sono solo curioso di sapere perché il ruolo non può essere consumato in quanto tale. – ozzmotik

risposta

1

Prima di tutto, devo concordare con Piers che tecnicamente dovresti chiamarlo come with 'Trello::API::Roles::Authable'.

Quindi, stai chiedendo qualcosa che non trovo da implementare in Moose di base. Ho già usato le idee dei pool di spazi dei nomi generici. Sono una sorta di namespace universali a cui puoi offrire i tuoi servizi semi-anonimi - senza il lock-in di uno spazio dei nomi fisso. Ho perfezionato la mia idea di base del pool di namespace con il supporto Moose (veramente MOP).

Nei giorni Wild West di Perl, tutto si dovrebbe fare è assegnare una scorta al simbolo per l'altro, in questo modo:

{ no strict 'refs'; 
    *{$short_pkg_name.'::'} = \*{$full_pkg_name.'::'}; 
}; 

E, quei due pacchetti erano esattamente le stesse cose!

Ma ora, proteggiamo i nostri dati con lessici un po 'di più. E poiché Class :: MOP custodisce gelosamente i suoi meta-oggetti in un hash lessicale, si deve aggiungere un'altra cosa:

Class::MOP::store_metaclass_by_name( 
     $short_pkg_name 
    , Class::MOP::get_metaclass_by_name($full_pkg_name) 
    ); 

ora sono la stessa identica cosa a Perl e MOP.

Così puoi creare pacchetti che sono semplicemente un repository di namespace per altri pacchetti - Ora con supporto MOP!

package Namespace::Pool; 
use strict; 
use warnings; 
use Params::Util qw<_POSINT>; 

sub import { 
    shift; # It's just me. 
    my $full_pkg_name = caller(); 
    Carp::croak("'$full_pkg_name' is short enough!") 
     unless my $pool_name 
      = shift // [ split /::/, $full_pkg_name ]->[-2] 
      ; 
    Carp::croak("'::$pool_name\::' not found in '$full_pkg_name'") 
     unless ( _POSINT(my $pos = rindex($full_pkg_name, "::$pool_name\::")) 
       or my $is_short = _POSINT(index($pool_name, '::')) 
       ); 
    my $short_pkg_name 
     = $is_short ? $poll_name 
     :    substr($full_pkg_name, $pos + 2) 
     ; 
    { no strict 'refs'; 
     if (%{$short_pkg_name.'::'}) { 
      Carp::croak("You have already defined $short_pkg_name!"); 
     } 
     *{$short_pkg_name.'::'} = \*{$full_pkg_name.'::'}; 
    }; 

    if (my $meta = Class::MOP::get_metaclass_by_name($full_pkg_name)) { 
     Class::MOP::store_metaclass_by_name($short_pkg_name, $meta); 
    } 
    return; 
} 

Così nel pacchetto di ruolo è possibile effettuare le seguenti operazioni:

package Trello::API::Roles::Authable; 
use strict; 
use warnings; 
use Moose::Role; 
use Namespace::Pool 'Roles'; 
... 

e sapere che sarà disponibile dallo spazio dei nomi dei 'ruoli'.

+0

Lo apprezzo molto. Ho finito per usare solo il nome completo del ruolo dopo che ho capito che stava funzionando, quindi il problema è stato risolto, ma la tua spiegazione è stata estremamente approfondita e ha fornito una buona base di partenza per ottenere ciò che stavo tentando di fare, quindi grazie tu tanto per il tuo impegno. – ozzmotik

0

Nel mio caso ho semplicemente accidentalmente chiamato il mio ruolo "Test", ma sul mio sistema c'era già un modulo chiamato "Test" e quindi Moose pensava che volessi utilizzare quel modulo piuttosto che il nuovo ruolo di Moose I creato. Una volta che ho ribattezzato per ruolo in 'Testable', tutto ha funzionato bene.

Problemi correlati