2012-05-24 11 views
5

Aloha!Componer roles en una clase Moose no funciona

Tengo un rol que estoy ocupado definiendo en una clase de Moose llamada Authable que está esencialmente compuesta en cualquier clase que podría requerir alguna forma de autenticación en el futuro; Es un papel bastante simple, aquí está la totalidad:

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

use Moose::Role; 

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

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

1; 

Por alguna razón, cuando intento de componer en una clase utilizando varias instrucciones diferentes, es decir, con " Trello :: API :: Roles :: Authable "; o con "Roles :: Authable";

que constantemente sale este mismo mensaje de error: You can only consume roles, Roles::Authable is not a Moose role.

Alguna idea de por qué esto podría estar sucediendo?

¡Editar!

Sólo una nota, he comprobado la fuente real de Moose :: Role, y vi esta bits:

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

Ésta parece ser donde se está produciendo el error, por lo que casi parece que por alguna razón , el rol que estoy implementando no dice que sea un rol en la metaclase. ¡Aunque podría estar equivocado! Cualquier ayuda sería apreciada.

Otro conveniente EDIT!

Bonificación: contexto de código en el que se llama a la rutina.

package Trello::API::Resource; 

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


with 'Roles::Authable'; 

el que cuando hago esto, se sabe de forma inteligente para tratar de consumir Roles/Authable.pm pero por alguna razón, simplemente no funciona!

+1

¿Qué quiere decir con "múltiples declaraciones diferentes"? ¿Estás haciendo 'con 'Trello :: API :: Roles :: Authable'' o' con' Roles :: Authable '; '? Porque no parece tener un rol con este último nombre. – friedo

+0

[¿Estás 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

Lo que quiero decir es que he probado múltiples variaciones diferentes; en este punto, el archivo que intenta consumir la función es Trello :: API :: Resource, por lo que parece reconocer Roles :: Authable como Trello :: API :: Roles :: Authable e intenta consumir ese módulo. En este punto, no va a reconocer dónde están los módulos ya que no los he puesto en la estructura del directorio del módulo actual; Siempre pude modificar @INC, pero en este momento tengo curiosidad por saber por qué el rol no se puede consumir como tal. – ozzmotik

Respuesta

1

Antes que nada, tengo que estar de acuerdo con los muelles en que técnicamente, realmente debería llamarlo como with 'Trello::API::Roles::Authable'.

Por lo tanto, estás pidiendo algo que no encuentro implementado en Moose básico. He utilizado las ideas de grupos de espacios de nombres genéricos antes. Son una especie de espacios de nombres universales a los que puede ofrecer sus servicios semianónimos , sin el bloqueo de un espacio de nombre fijo. He refinado mi idea básica del grupo de espacios de nombres con soporte para Moose (realmente MOP).

En los días del Salvaje Oeste de Perl, todo lo que tendría que hacer es asignar un escondite al símbolo para el otro, así:

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

Y, esos dos paquetes fueron exactamente las mismas cosas!

Pero ahora protegemos nuestros datos con léxicos un poco más. Y debido a que la clase :: MOP guarda celosamente sus objetos meta en un hash léxico, hay que añadir algo más:

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

Ahora ellos son exactamente lo mismo que a Perl y al MOP.

Así puede crear paquetes que son simplemente un repositorio de espacio de nombres para otros paquetes - ¡Ahora con soporte 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; 
} 

Así, en su paquete de papel que usted puede hacer lo siguiente:

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

y saber que estará disponible a partir del espacio de nombres de 'roles'.

+0

Lo aprecio mucho. Terminé simplemente usando el nombre completamente calificado de la función después de darme cuenta de que estaba funcionando, así que el problema fue resuelto, pero tu explicación fue extremadamente profunda y proporcionó una buena base para lograr lo que estaba intentando hacer, así que gracias mucho por tu esfuerzo – ozzmotik

0

En mi caso, simplemente había nombrado accidentalmente mi función 'Prueba', pero ya había un módulo instalado en mi sistema llamado 'Prueba' y Moose pensó que quería consumir ese módulo en lugar del nuevo papel de Moose I había creado. Una vez que renombré mi rol por 'Testable', todo funcionó bien.

Cuestiones relacionadas