2010-04-01 78 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

相关问题