0

In Moose v1.x, I used to be able to do this:

package Class;
use Test::More tests => 1;
use Moose;
use MooseX::Types::Moose qw/Undef Str/;

eval {
  has 'trait_boom' => (
    is => 'rw'
    , isa => Str | Undef
    , default => ''
    , traits => ['String']
  );
};

ok ( !$@, "Created attr trait_boom, a type union of Str and Undef\n$@" );

However, it no longer works with Moose 2.x. I assume this is a bug. Why did Moose break backwards compatibility? Is there another way to get this job done. I want that to be either Undef or a Str. I do not want to coerce Undef to an empty string though.

I'm only asking here because apparently magnet is broke

17:43 [perl2] -!- ERROR Closing Link: 64.200.109.13 (Banned)
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468

2 Answers2

2

I would guess this was changed in Moose 2.0300, Fri, Sep 23, 2011:

  • The ->is_subtype_of and ->is_a_type_of methods have changed their behavior for union types. Previously, they returned true if any of their member types returned true for a given type. Now, all of the member types must return true. RT #67731. (Dave Rolsky)

Have you tried Maybe[Str] instead of Str | Undef?

cjm
  • 61,471
  • 9
  • 126
  • 175
2

As we told you on MagNet right after I reported you for ban evasion, this is not a bug. The trait's methods should never have worked against the value Undef, so allowing this behavior to work in 1.x was the bug. Moose has ways optimized for correct behavior and never promised bug compat between versions.

You will either need to write your own traits or write the methods by hand to deal with this situation.

perigrin
  • 4,433
  • 19
  • 22
  • Is there a more simple way to make the trait apply only if the attribute passes `is_Str()`? That sounds like a much better solution for this non problem. I used to just do `$foo->trait_provided_attribute if defined $foo->attribute;` That worked fine for me. – Evan Carroll Dec 13 '11 at 16:36
  • Attribute traits are applied when the class declaration, the value is only available when an object is instantiated, so it's too late to apply a trait there (some weird hacks excluded). Personally, I'd just make two attributes. – phaylon Dec 13 '11 at 18:05