2011-02-25 80 views
4

我想將Str強制轉換爲我的Moose類中屬性的DBIx :: Class :: Row對象。爲此,我需要在DBIC模式上執行查找以查找該行。如果查找失敗,我想將錯誤推送到ArrayRef屬性上。如何通過Moose強制訪問我的對象的屬性?

我當前將模式作爲屬性傳遞給我的類。

通過強制,它看起來我無法訪問對象,所以我不能推入錯誤arrayref屬性或使用模式對象來執行我的查找。

我試過的另一種方法是在設置時使用'around'來查找和設置屬性,但當通過構造函數傳遞屬性值時,這當然不會被調用。

這是可能的,還是有人有一個替代實現來做我想達到的目的?

回答

4

您可以在傳入構造函數時使用屬性初始值設定程序捕獲並更改存儲的值。 (但是,只有在屬性在構造函數中設置時纔會運行,而不是在任何其他時間運行。)有關初始化程序的文檔可以在Class::MOP::Attribute中找到。

由於這隻會捕獲通過構造函數設置屬性的情況,您仍需要捕獲設置屬性的其他情況。這可以用一個方法修改完成像你說的,但你可以在這兩個合併成一個方法,圍繞自動生成的存取包裹:

has my_attr => (
    is => 'rw', 
    isa => 'DBIx::Class::Row', 
    initializer => 'my_attr', 
); 

# my_attr is the autogenerated accessor - we method-modify it to mutate the 
# value being set, and catch cases where it is called as an initializer. 

# called for reads, writes, and on initialization at construction time 
around 'my_attr' => sub { 
    my $orig = shift; 
    my $self = shift; 
    # value is not defined if being called as a reader 
    # setter and attr are only defined if being called as an initializer 
    my ($value, $setter, $attr) = @_; 

    # the reader behaves normally 
    return $self->$orig if not @_; 

    # convert the string to the row object 
    my $row = $self->convert_str_to_row_obj($value); 

    # if called as an initializer, set the value and we're done 
    return $setter->($row) if $setter; 

    # otherwise, call the real writer with the new value 
    $self->$orig($row); 
}; 
+0

嗯 - 我認爲這將做到這一點,但是當我嘗試了,我得到'屬性(my_attr)不會傳遞類型約束,因爲:對於值爲'Foo'的'DBIx :: Class :: Row',驗證失敗。看起來類型約束在*初始化方法運行之前被檢查* – cubabit 2011-02-28 11:23:02

+0

我可能必須將isa更改爲'Str |目的' – cubabit 2011-02-28 14:56:01