2010-12-01 54 views
2

我想在穆斯創建一個結構化類型,可以用作另一個穆斯屬性的類型。例如,我希望能夠創建一個name屬性,該屬性具有其自己的valueerror屬性。穆斯結構類型

因此,我想知道實現這一目標的最佳方法。我創建了一個工作示例,定義了一個簡單的Moose類來表示一個通用的Field對象。這具有valueerror屬性。然後,我爲Person對象創建了另一個Moose類。這有idname屬性,這兩者都是Field類型:

定義一個通用的領域對象:

package MyApp::Type::Field; 
use Moose; 
use namespace::autoclean; 

has 'value' => (is => 'rw'); 
has 'error' => (is => 'rw', isa => 'Str'); 

__PACKAGE__->meta->make_immutable; 
1; 

定義一個使用領域對象Person對象:

package MyApp::Person; 
use Moose; 
use namespace::autoclean; 
use MyApp::Type::Field; 

has 'id' => (is => 'rw', isa => 'MyApp::Type::Field');  
has 'name' => (is => 'rw', isa => 'MyApp::Type::Field'); 

__PACKAGE__->meta->make_immutable; 
1; 

待辦事項Person對象:

package MyApp::Test; 

use Moose; 
use namespace::autoclean; 
use MyApp::Person; 

my $person = MyApp::Person->new(); 

# This works. 
$person->id(MyApp::Type::Field->new()); 
$person->id->value(1); 
$person->id->error('Not found'); 

# This fails as the name object has not yet been defined. 
$person->name->value('Dave'); 
# Can't call method "value" on an undefined value at ... 

__PACKAGE__->meta->make_immutable; 
1; 

這是有效的,但在MyApp::Test我希望能夠直接訪問該人的nameidvalueerror屬性,而不必爲每個人的屬性實例化一個新的MyApp::Type::Field對象。

或者換句話說,如果Person類的用戶在使用id屬性之前不需要這樣做:$person->id(MyApp::Type::Field->new());

是否有一個很好的乾淨的方式,我可以實現這一目標?

回答

1

難道你不能簡單地提供一個default的屬性?

has 'id' => (
    is => 'rw', 
    isa => 'MyApp::Type::Field', 
    default => sub { MyApp::Type::Field->new } 
); 

...或做相應的BUILD

+0

是啊,突然間它似乎很明顯。 :-) 謝謝你的幫助。 – Mike 2010-12-01 12:59:33

1

您也可以嘗試強制:

coerce 'MyApp::Type::Field' 
    => from 'Int' 
    => via { MyApp::Type::Field->new(value => shift) } 
    ; 

這樣,它只是:

$person->id(1); 

來設置。雖然設置錯誤仍然需要按照您的方式進行。


我也許應該提到的是,你需要做到以下幾點:

  • 添加Moose::Util::TypeConstraints到你把coerce包。
  • 添加coerce標誌字段:

    has id => (is => 'rw', isa => 'MyApp::Type::Field', coerce => 1); 
    
+0

謝謝你。我實際上已經從Str和HashRef中添加了強制,這使得我可以像這樣創建一個新Person:`$ person = MyApp :: Person-> new(id => {value => 1,error =>'未找到'},name => {value =>'Dave'});` – Mike 2010-12-01 16:36:02