Revision history for Perl extension Moose
-0.04
+0.04 Sun. April 16th, 2006
* Moose::Role
- Roles can now consume other roles
- added tests for this
* Moose::Meta::Attribute
- added support for triggers on attributes
- added tests for this
+ - added support for does option on an attribute
+ - added tests for this
* Moose::Meta::Class
- added support for attribute triggers in the
t/004_basic.t
t/005_basic.t
t/006_basic.t
+t/007_basic.t
t/010_basic_class_setup.t
t/011_require_superclasses.t
t/012_super_and_override.t
t/030_attribute_reader_generation.t
t/031_attribute_writer_generation.t
t/032_attribute_accessor_generation.t
+t/033_attribute_triggers.t
+t/034_does_attribute_option.t
t/040_meta_role.t
t/041_role.t
t/042_apply_role.t
+t/043_role_composition_errors.t
t/050_util_type_constraints.t
t/051_util_type_constraints_export.t
t/052_util_std_type_constraints.t
t/055_util_type_reloading.t
t/056_util_more_type_coercion.t
t/100_subtype_quote_bug.t
+t/101_subtype_conflict_bug.t
+t/102_Moose_Object_error.t
t/pod.t
t/pod_coverage.t
t/lib/Bar.pm
t/lib/Foo.pm
+t/lib/MyMooseA.pm
+t/lib/MyMooseB.pm
+t/lib/MyMooseObject.pm
-Moose version 0.03_02
+Moose version 0.04
===========================
See the individual module documentation for more information
}
if (exists $options{isa}) {
+
+ if (exists $options{does}) {
+ if (eval { $options{isa}->can('does') }) {
+ ($options{isa}->does($options{does}))
+ || confess "Cannot have an isa option and a does option if the isa does not do the does";
+ }
+ }
+
# allow for anon-subtypes here ...
if (blessed($options{isa}) && $options{isa}->isa('Moose::Meta::TypeConstraint')) {
$options{type_constraint} = $options{isa};
$options{type_constraint} = $constraint;
}
}
+ elsif (exists $options{does}) {
+ # allow for anon-subtypes here ...
+ if (blessed($options{does}) && $options{does}->isa('Moose::Meta::TypeConstraint')) {
+ $options{type_constraint} = $options{isa};
+ }
+ else {
+ # otherwise assume it is a constraint
+ my $constraint = Moose::Util::TypeConstraints::find_type_constraint($options{does});
+ # if the constraing it not found ....
+ unless (defined $constraint) {
+ # assume it is a foreign class, and make
+ # an anon constraint for it
+ $constraint = Moose::Util::TypeConstraints::subtype(
+ 'Role',
+ Moose::Util::TypeConstraints::where { $_->does($options{does}) }
+ );
+ }
+ $options{type_constraint} = $constraint;
+ }
+ }
if (exists $options{coerce} && $options{coerce}) {
(exists $options{type_constraint})
=item B<is_weak_ref>
-Returns true of this meta-attribute produces a weak reference.
+Returns true if this meta-attribute produces a weak reference.
=item B<is_required>
-Returns true of this meta-attribute is required to have a value.
+Returns true if this meta-attribute is required to have a value.
=item B<is_lazy>
-Returns true of this meta-attribute should be initialized lazily.
+Returns true if this meta-attribute should be initialized lazily.
NOTE: lazy attributes, B<must> have a C<default> field set.
=item B<should_coerce>
-Returns true of this meta-attribute should perform type coercion.
+Returns true if this meta-attribute should perform type coercion.
=item B<has_trigger>
+Returns true if this meta-attribute has a trigger set.
+
=item B<trigger>
+This is a CODE reference which will be executed every time the
+value of an attribute is assigned. The CODE ref will get two values,
+the invocant and the new value. This can be used to handle I<basic>
+bi-directional relations.
+
=back
=head1 BUGS
=item B<new_object>
+We override this method to support the C<trigger> attribute option.
+
=item B<construct_instance>
This provides some Moose specific extensions to this method, you
=item B<add_override_method_modifier ($name, $method)>
+This will create an C<override> method modifier for you, and install
+it in the package.
+
=item B<add_augment_method_modifier ($name, $method)>
+This will create an C<augment> method modifier for you, and install
+it in the package.
+
=item B<roles>
+This will return an array of C<Moose::Meta::Role> instances which are
+attached to this class.
+
=item B<add_role ($role)>
+This takes an instance of C<Moose::Meta::Role> in C<$role>, and adds it
+to the list of associated roles.
+
=item B<does_role ($role_name)>
+This will test if this class C<does> a given C<$role_name>. It will
+not only check it's local roles, but ask them as well in order to
+cascade down the role hierarchy.
+
=back
=head1 BUGS
=head1 DESCRIPTION
Moose's Roles are being actively developed, please see L<Moose::Role>
-for more information.
+for more information. For the most part, this has no user-serviceable
+parts inside. It's API is still subject to some change (although
+probably not that much really).
=head1 METHODS
=item B<does ($role_name)>
+This will check if the invocant's class C<does> a given C<$role_name>.
+This is similar to C<isa> for object, but it checks the roles instead.
+
=back
=head1 BUGS
# we should never export to main
return if $pkg eq 'main';
-
- Moose::Util::TypeConstraints->import($pkg);
my $meta;
if ($pkg->can('meta')) {
=head1 DESCRIPTION
This is currently a very early release of Perl 6 style Roles for
-Moose, it should be considered experimental and incomplete.
-
-This feature is being actively developed, but $work is currently
-preventing me from paying as much attention to it as I would like.
-So I am releasing it in hopes people will help me on this I<hint hint>.
-
-If you are interested in helping, please come to #moose on irc.perl.org
-and we can talk.
+Moose, it is still incomplete, but getting much closer. If you are
+interested in helping move this feature along, please come to
+#moose on irc.perl.org and we can talk.
=head1 CAVEATS
-Currently, the role support has a number of caveats. They are as follows:
+Currently, the role support has a few of caveats. They are as follows:
=over 4
=item *
-At this time classes I<can> consume more than one Role, but they are simply
-applied one after another in the order you ask for them. This is incorrect
-behavior, the roles should be merged first, and conflicts determined, etc.
-However, if your roles do not have any conflicts, then things will work just
-fine.
+At this time classes I<cannot> correctly consume more than one role. The
+role composition process, and it's conflict detection has not been added
+yet. While this should be considered a major feature, it can easily be
+worked around, and in many cases, is not needed at all.
+
+A class can actually consume multiple roles, they are just applied one
+after another in the order you ask for them. This is incorrect behavior,
+the roles should be merged first, and conflicts determined, etc. However,
+if your roles do not have any conflicts, then things will work just
+fine. This actually tends to be quite sufficient for basic roles.
=item *
=back
-Basically thats all I can think of for now, I am sure there are more though.
-
=head1 BUGS
All complex software has bugs lurking in it, and this module is no
# blessed(qr/.../) returns true,.. how odd
subtype 'Object' => as 'Ref' => where { blessed($_) && blessed($_) ne 'Regexp' };
+subtype 'Role' => as 'Object' => where { $_->can('does') };
+
1;
__END__
CodeRef
RegexpRef
Object
+ Role
Suggestions for improvement are welcome.
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+use Test::Exception;
+
+BEGIN {
+ use_ok('Moose');
+}
+
+{
+ package Foo::Role;
+ use strict;
+ use warnings;
+ use Moose::Role;
+
+ # if does() exists on its own, then
+ # we create a type constraint for
+ # it, just as we do for isa()
+ has 'bar' => (is => 'rw', does => 'Bar::Role');
+
+ package Bar::Role;
+ use strict;
+ use warnings;
+ use Moose::Role;
+
+ # if isa and does appear together, then see if Class->does(Role)
+ # if it does work... then the does() check is actually not needed
+ # since the isa() check will imply the does() check
+ has 'foo' => (is => 'rw', isa => 'Foo::Class', does => 'Foo::Role');
+
+ package Foo::Class;
+ use strict;
+ use warnings;
+ use Moose;
+
+ with 'Foo::Role';
+
+ package Bar::Class;
+ use strict;
+ use warnings;
+ use Moose;
+
+ with 'Bar::Role';
+
+}
+
+my $foo = Foo::Class->new;
+isa_ok($foo, 'Foo::Class');
+
+my $bar = Bar::Class->new;
+isa_ok($bar, 'Bar::Class');
+
+lives_ok {
+ $foo->bar($bar);
+} '... bar passed the type constraint okay';
+
+dies_ok {
+ $foo->bar($foo);
+} '... foo did not pass the type constraint okay';
+
+lives_ok {
+ $bar->foo($foo);
+} '... foo passed the type constraint okay';
+
+# some error conditions
+
+{
+ package Baz::Class;
+ use strict;
+ use warnings;
+ use Moose;
+
+ # if isa and does appear together, then see if Class->does(Role)
+ # if it does not,.. we have a conflict... so we die loudly
+ ::dies_ok {
+ has 'foo' => (isa => 'Foo::Class', does => 'Bar::Class');
+ } '... cannot have a does() which is not done by the isa()';
+}
+
use strict;
use warnings;
-use Test::More tests => 111;
+use Test::More tests => 122;
use Test::Exception;
use Scalar::Util ();
ok(!defined Object($SCALAR_REF), '... Object rejects anything which is not blessed');
ok(!defined Object(qr/../), '... Object rejects anything which is not blessed');
ok(defined Object(bless {}, 'Foo'), '... Object accepts anything which is blessed');
+
+{
+ package My::Role;
+ sub does { 'fake' }
+}
+
+ok(!defined Role(0), '... Role rejects anything which is not a Role');
+ok(!defined Role(100), '... Role rejects anything which is not a Role');
+ok(!defined Role(''), '... Role rejects anything which is not a Role');
+ok(!defined Role('Foo'), '... Role rejects anything which is not a Role');
+ok(!defined Role([]), '... Role rejects anything which is not a Role');
+ok(!defined Role({}), '... Role rejects anything which is not a Role');
+ok(!defined Role(sub {}), '... Role rejects anything which is not a Role');
+ok(!defined Role($SCALAR_REF), '... Role rejects anything which is not a Role');
+ok(!defined Role(qr/../), '... Role rejects anything which is not a Role');
+ok(!defined Role(bless {}, 'Foo'), '... Role accepts anything which is not a Role');
+ok(defined Role(bless {}, 'My::Role'), '... Role accepts anything which is not a Role');
+
+