2010-04-01 89 views
6

我目前使用eval塊來測試我已經將屬性設置爲只讀。有沒有更簡單的方法來做到這一點?從工作中有沒有簡單的方法來測試Moose屬性是否只讀?

例子:

#Test that sample_for is ready only 
eval { $snp_obj->sample_for('t/sample_manifest2.txt');}; 
like([email protected], qr/read-only/xms, "'sample_for' is read-only"); 



UPDATE

感謝friedo,乙醚和羅伯特·P代表他們的答案和醚,羅伯特·P和jrockway徵求意見。

我喜歡甲醚的答案如何確保$is_read_only僅僅是一個真或假的值(即卻從CODEREF)通過用!否定它。 Double negation也提供。因此,您可以在is()函數中使用$is_read_only,而無需打印出coderef。

有關最完整的答案,請參見下面的Robert P的答案。每個人都非常有幫助,並建立在彼此的答案和評論。總體而言,我認爲他對我的幫助最大,因此他現在被標記爲接受的答案。再次感謝Ether,Robert P,friedo和jrockway。



萬一你可能想知道的,當我第一次做,這裏是約get_attributefind_attribute_by_namefrom Class::MOP::Class)之間的區別文檔:

$metaclass->get_attribute($attribute_name) 

    This will return a Class::MOP::Attribute for the specified $attribute_name. If the 
    class does not have the specified attribute, it returns undef. 

    NOTE that get_attribute does not search superclasses, for that you need to use 
    find_attribute_by_name. 
+0

這將是更好的寫作'OK($ snp_obj - > meta-> get_attribute('sample_for') - > get_write_method(),''sample_for'是隻讀的「);' - 在測試失敗時,is()'輸出第二個參數(這將是一個coderef )..更不用說你有第一個和第二個參數相反了:'是($ has,$ expected,$ test_name)'。 – Ether 2010-04-01 19:19:56

+0

如果你的@attribute_names數組是精心構造的,你應該沒問題;但如果該屬性不存在,您將爆炸:) – 2010-04-02 16:55:10

+0

+1注意如何在超類中定位屬性 – user1027562 2013-06-27 15:16:59

回答

5

從技術上講,屬性不需要有讀取或寫入方法。 大部分是,但並不總是如此。一個例子(從jrockway's comment慷慨被盜)低於:

has foo => ( 
    isa => 'ArrayRef', 
    traits => ['Array'], 
    handles => { add_foo => 'push', get_foo => 'pop' } 
) 

此屬性將存在,​​但沒有標準讀者和作家。

因此,要在每種情況下測試屬性已被定義爲is => 'RO',您需要檢查寫入和讀取方法。你可以用這個子程序做到這一點:

# returns the read method if it exists, or undef otherwise. 
sub attribute_is_read_only { 
    my ($obj, $attribute_name) = @_; 
    my $attribute = $obj->meta->get_attribute($attribute_name); 

    return unless defined $attribute; 
    return (! $attribute->get_write_method() && $attribute->get_read_method()); 
} 

或者,你可以在最後return前添加一個雙重否定到boolify返回值:

return !! (! $attribute->get_write_method() && $attribute->get_read_method()); 
+1

我喜歡第一個例子;) – jrockway 2010-04-02 23:51:29

5

正如Class::MOP::Attribute記載:

my $attr = $this->meta->find_attribute_by_name($attr_name); 
my $is_read_only = ! $attr->get_write_method(); 

$attr->get_write_method()將得到作家的方法(無論是你cr或者是生成的),或者如果沒有一個,則爲undef。

+0

謝謝!知道它返回'undef'允許單行測試(我嘗試在這裏發佈它,但它看起來不太漂亮)。 – 2010-04-01 18:59:41

+0

嗯,實際上...測試它是否有寫入方法。儘管如此,它不會測試它是否具有讀取方法。在技​​術上它不一定非得。這不是一個非常有用的屬性,如果它不是,但你可以擁有它! – 2010-04-01 23:36:29

+0

@羅伯特:是的,嚴格來說,它檢查屬性是「不可寫」(不是isa =>'rw'),這與「只讀」(isa =>'ro')不完全相同。 – Ether 2010-04-01 23:55:44

3

您應該能夠從對象的元類得到這樣的:

unless ($snp_obj->meta->get_attribute('sample_for')->get_write_method) { 
    # no write method, so it's read-only 
} 

更多見Class::MOP::Attribute

+0

謝謝!那是我需要的。 – 2010-04-01 18:59:10

相關問題