Also see Moose::Manual::Delta for more details of, and workarounds
for, noteworthy changes.
-
+0.88
* Moose::Meta::Attribute
- Added the currying syntax for delegation from AttributeHelpers
to the existing delegation API. (hdp)
- Moved in from MooseX with API tweaks. See Moose::Manual::Delta for
details. (hdp, jhannah, rbuels)
+0.87 Tue Jul 7, 2009
+ * Moose::Meta::Method::Delegation
+ - Once again allow class names as well as objects for
+ delegation. This was changed in 0.86.
+
+0.86 Fri Jul 3, 2009
+ * Moose::Meta::Class::Immutable::Trait
+ - Fixes to work with the latest Class::MOP.
+
+ * Moose::Meta::Method::Delegation
+ - Delegation now dies with a more useful error message if the
+ attribute's accessor returns something defined but
+ unblessed. (hdp)
+
0.85 Fri, Jun 26, 2009
* Moose::Meta::Attribute
- The warning for 'no associated methods' is now split out into
requires 'Scalar::Util' => '1.19';
requires 'Carp';
-requires 'Class::MOP' => '0.88';
+requires 'Class::MOP' => '0.89';
requires 'List::MoreUtils' => '0.12';
requires 'Sub::Exporter' => '0.980';
requires 'Task::Weaken' => '0';
-Moose version 0.85
+Moose version 0.87
===========================
See the individual module documentation for more information
use 5.008;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Exporter;
-use Class::MOP 0.88;
+use Class::MOP 0.89;
use Moose::Meta::Class;
use Moose::Meta::TypeConstraint;
becomes the list of methods to handle. The "interface" can be defined as; the
list of methods passed to C<duck_type> to create a duck type object. For more
information on C<duck_type> please check
-L<Moose::Util::TypeConstraint|Moose::Util::TypeConstraint>.
+L<Moose::Util::TypeConstraints>.
=item C<CODE>
=item B<around $name|@names =E<gt> sub { ... }>
-This three items are syntactic sugar for the before, after, and around method
+These three items are syntactic sugar for the before, after, and around method
modifier features that L<Class::MOP> provides. More information on these may be
found in the L<Class::MOP::Class documentation|Class::MOP::Class/"Method
Modifiers"> for now.
=head1 NAME
-Moose::Cookbook::Basics::Recipe11 - Using BUILDARGS and BUILD to hook into object construction
+Moose::Cookbook::Basics::Recipe10 - Using BUILDARGS and BUILD to hook into object construction
=head1 SYNOPSIS
=head1 NAME
-Moose::Cookbook::Basics::Recipe12 - Extending a non-Moose base class
+Moose::Cookbook::Basics::Recipe11 - Extending a non-Moose base class
=head1 SYNOPSIS
=head1 NAME
-Moose::Cookbook::Basics::Recipe10 - Operator overloading, subtypes, and coercion
+Moose::Cookbook::Basics::Recipe9 - Operator overloading, subtypes, and coercion
=head1 SYNOPSIS
=head1 ROLES VS TRAITS VS SUBCLASSES
-It is important to understand that B<roles and traits are the same
-thing>. A role can be used as a trait, and a trait is a role. The only
-thing that distinguishes the two is that a trait is packaged in a way
-that lets Moose resolve a short name to a class name. In other words,
-with a trait, the caller can refer to it by a short name like "Big",
-and Moose will resolve it to a class like
-C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
+It is important to understand that B<roles and traits are the same thing>. A
+trait is simply a role applied to a metaclass. The only thing that may
+distinguish the two is that a trait can be packaged in a way that lets Moose
+resolve a short name to a class name. In other words, with a trait, the caller
+can refer to it by a short name like "Big", and Moose will resolve it to a
+class like C<MooseX::Embiggen::Meta::Attribute::Role::Big>.
See L<Moose::Cookbook::Meta::Recipe3> and
L<Moose::Cookbook::Meta::Recipe5> for examples of traits in action. In
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
documentation, but you can see how Moose reduces common OO idioms to
simple declarative constructs.
-=head2 TABLE OF CONTENTS
+=head1 TABLE OF CONTENTS
This manual consists of a number of documents.
1;
-The C<no Moose> bit is simply good code hygiene, and making classes
-immutable speeds up a lot of things, most notably object construction.
+The C<no Moose> bit is simply good code hygiene, as it removes all the
+Moose keywords from your class's namespace. Once the class has been
+built, these keywords are not needed needed. The C<make_immutable>
+call allows Moose to speed up a lot of things, most notably object
+construction. The tradeoff is that you can no longer change the class
+definition.
+
+A more generic way to unimport not only L<Moose>'s exports but also
+those from type libraries and other modules is to use
+L<namespace::clean> or L<namespace::autoclean>.
=head2 Never override C<new>
Lazy is good, and often solves initialization ordering problems. It's
also good for deferring work that may never have to be done. If you're
-going to be lazy, use I<lazy_build> to save yourself some typing and
+going to be lazy, use C<lazy_build> to save yourself some typing and
standardize names.
=head2 Consider keeping clearers and predicates private
writer a separate private method. Narrower APIs are easy to maintain,
and mutable state is trouble.
+In order to declare such attributes, provide a private C<writer>
+parameter:
+
+ has pizza => (
+ is => 'ro',
+ isa => 'Pizza',
+ writer => '_pizza',
+ );
+
=head2 Think twice before changing an attribute's type in a subclass
Down this path lies great confusion. If the attribute is an object
=head1 GETTING INVOLVED
Moose is a pretty open project and we are always willing to accept bug
-fixes, more tests and doc patches. Doing these things is as simple as
-cloning a copy of the git repository and hacking.
+fixes, more tests and documentation patches. Doing these things is as simple as
+cloning a copy of the Git repository and hacking.
Commit bits are given out freely. All we ask is that for any
non-trivial code patches, you check with one of the core developers
before applying said patch.
Alternatively, you can make a new branch with your change and push it
-back to the Moose git server, then ask a core dev to review your
+back to the Moose Git server, then ask a core dev to review your
branch.
=head2 IRC and Email
Moose will no longer inline a constructor for your class unless it
inherits its constructor from Moose::Object, and will warn when it
doesn't inline. If you want to force inlining anyway, pass
-C<< "replace_constructor => 1 >> to C<make_immutable>.
+C<< replace_constructor => 1 >> to C<make_immutable>.
If you want to get rid of the warning, pass C<< inline_constructor =>
0 >>.
=head3 Why is BUILD not called for my composed roles?
-BUILD is never called in composed roles. The primary reason is that
+C<BUILD> is never called in composed roles. The primary reason is that
roles are B<not> order sensitive. Roles are composed in such a way
that the order of composition does not matter (for information on the
deeper theory of this read the original traits papers here
L<http://www.iam.unibe.ch/~scg/Research/Traits/>).
Because roles are essentially unordered, it would be impossible to
-determine the order in which to execute the BUILD methods.
+determine the order in which to execute the C<BUILD> methods.
As for alternate solutions, there are a couple.
class_has 'Cache' => ( ... );
-Note however that this class attribute does -not- inherit like a
+Note however that this class attribute does I<not> inherit like a
L<Class::Data::Inheritable> or similar attribute - calling
$subclass->Cache($cache);
the new name. We also need to exclude the original name:
with 'Breakable' => {
- alias => { break => 'break_bone' },
- exclude => 'break',
+ alias => { break => 'break_bone' },
+ excludes => 'break',
},
'Breakdancer' => {
- alias => { break => 'break_dance' },
- exclude => 'break',
+ alias => { break => 'break_dance' },
+ excludes => 'break',
};
-The exclude parameter prevents the C<break> method from being composed
+The excludes parameter prevents the C<break> method from being composed
into the C<FragileDancer> class, so we don't have a conflict. This
means that C<FragileDancer> does not need to implement its own
C<break> method.
use Scalar::Util 'blessed', 'weaken';
use overload ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Method::Accessor;
&& (!$self->definition_context
|| $method->package_name eq $self->definition_context->{package})) {
Carp::cluck(
- "You cannot overwrite a locally defined method ($accessor) with "
+ "You are overwriting a locally defined method ($accessor) with "
. "an accessor"
);
}
use List::MoreUtils qw( any all uniq first_index );
use Scalar::Util 'weaken', 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base 'Class::MOP::Class::Immutable::Trait';
-sub add_role { shift->_immutable_cannot_call }
+sub add_role { $_[1]->_immutable_cannot_call }
sub calculate_all_roles {
- @{ $_[0]{__immutable}{calculate_all_roles} ||= [ shift->next::method ] };
+ my $orig = shift;
+ my $self = shift;
+ @{ $self->{__immutable}{calculate_all_roles} ||= [ $self->$orig ] };
}
1;
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed', 'weaken', 'looks_like_number', 'refaddr';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
our $AUTHORITY = 'cpan:STEVAN';
use base 'Moose::Meta::Method',
use Carp 'confess';
use Scalar::Util 'blessed', 'weaken';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
$self->{body} = sub {
my $instance = shift;
my $proxy = $instance->$accessor();
- ( defined $proxy )
- || $self->throw_error(
- "Cannot delegate $handle_name to $method_to_call because "
- . "the value of "
- . $self->associated_attribute->name
- . " is not defined",
- method_name => $method_to_call,
- object => $instance
+
+ my $error
+ = !defined $proxy ? ' is not defined'
+ : ref($proxy) && !blessed($proxy) ? qq{ is not an object (got '$proxy')}
+ : undef;
+
+ if ($error) {
+ $self->throw_error(
+ "Cannot delegate $handle_name to $method_to_call because "
+ . "the value of "
+ . $self->associated_attribute->name
+ . $error,
+ method_name => $method_to_call,
+ object => $instance
);
+ }
my @args = (@{ $self->curried_arguments }, @_);
$proxy->$method_to_call(@args);
};
use Scalar::Util 'blessed', 'weaken';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Sub::Name 'subname';
use Devel::GlobalDestruction 'in_global_destruction';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
This method accepts a list of array references. Each array reference
should contain a role name as its first element. The second element is
-an optional hash reference. The hash reference can contain C<exclude>
+an optional hash reference. The hash reference can contain C<excludes>
and C<alias> keys to control how methods are composed from the role.
The return value is a new L<Moose::Meta::Role::Composite> that
use warnings;
use metaclass;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Role::Composite;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util 'english_list';
use Scalar::Util 'weaken', 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base qw(Moose::Meta::Role::Method::Required);
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base qw(Class::MOP::Object);
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::Attribute;
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use base qw(Class::MOP::Object);
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use warnings;
use metaclass;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util::TypeConstraints;
use Moose::Meta::TypeConstraint::Parameterizable;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util 'blessed';
use Moose::Util::TypeConstraints ();
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Meta::TypeCoercion::Union;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use if ( not our $__mx_is_compiled ), 'Moose::Meta::Class';
use if ( not our $__mx_is_compiled ), metaclass => 'Moose::Meta::Class';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Sub::Exporter;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
=head1 DESCRIPTION
-The concept of roles is documented in L<Moose::Manual::Role>. This document
+The concept of roles is documented in L<Moose::Manual::Roles>. This document
serves as API documentation.
=head1 EXPORTED FUNCTIONS
use Scalar::Util 'blessed';
use Class::MOP 0.60;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
The C<$applicant> must already have a metaclass object.
The list of C<@roles> should be a list of names, each of which can be
-followed by an optional hash reference of options (C<exclude> and
+followed by an optional hash reference of options (C<excludes> and
C<alias>).
=item B<ensure_all_roles($applicant, @roles)>
use strict;
use warnings;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Scalar::Util qw( blessed reftype );
use Moose::Exporter;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
use Scalar::Util 'blessed', 'looks_like_number';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Moose::Util 'does_role', 'find_meta';
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
use Class::MOP;
-our $VERSION = '0.85';
+our $VERSION = '0.87';
$VERSION = eval $VERSION;
our $AUTHORITY = 'cpan:STEVAN';
can_ok('Foo', 'does');
foreach my $function (qw(
- extends
- has
- before after around
- blessed confess
- type subtype as where
- coerce from via
- find_type_constraint
- )) {
+ extends
+ has
+ before after around
+ blessed confess
+ type subtype as where
+ coerce from via
+ find_type_constraint
+ )) {
ok(!Foo->meta->has_method($function), '... the meta does not treat "' . $function . '" as a method');
}
use strict;
use warnings;
-use Test::More tests => 89;
+use Test::More tests => 92;
use Test::Exception;
has 'bar' => (is => 'rw', default => 10);
+ sub baz { 42 }
+
package Bar;
use Moose;
default => sub { Foo->new },
handles => {
'foo_bar' => 'bar',
+ foo_baz => 'baz',
'foo_bar_to_20' => [ bar => [ 20 ] ],
- }
+ },
);
}
my $self = shift;
my $name = our $AUTOLOAD;
- $name =~ s/.*://; # strip fully-qualified portion
+ $name =~ s/.*://; # strip fully-qualified portion
if (@_) {
return $self->{$name} = shift;
ok(!$i->meta->has_method('foo_bar'), 'handles method foo_bar is removed');
}
+# Make sure that a useful error message is thrown when the delegation target is
+# not an object
+{
+ my $i = Bar->new(foo => undef);
+ throws_ok { $i->foo_bar } qr/is not defined/,
+ 'useful error from unblessed reference';
+
+ my $j = Bar->new(foo => []);
+ throws_ok { $j->foo_bar } qr/is not an object \(got 'ARRAY/,
+ 'useful error from unblessed reference';
+
+ my $k = Bar->new(foo => "Foo");
+ lives_ok { $k->foo_baz } "but not for class name";
+}
my $foo_meta = Foo->meta;
stderr_like(sub { $foo_meta->add_attribute(a => (reader => 'get_a')) },
- qr/^You cannot overwrite a locally defined method \(get_a\) with an accessor/, 'reader overriding gives proper warning');
+ qr/^You are overwriting a locally defined method \(get_a\) with an accessor/, 'reader overriding gives proper warning');
stderr_like(sub { $foo_meta->add_attribute(b => (writer => 'set_b')) },
- qr/^You cannot overwrite a locally defined method \(set_b\) with an accessor/, 'writer overriding gives proper warning');
+ qr/^You are overwriting a locally defined method \(set_b\) with an accessor/, 'writer overriding gives proper warning');
stderr_like(sub { $foo_meta->add_attribute(c => (predicate => 'has_c')) },
- qr/^You cannot overwrite a locally defined method \(has_c\) with an accessor/, 'predicate overriding gives proper warning');
+ qr/^You are overwriting a locally defined method \(has_c\) with an accessor/, 'predicate overriding gives proper warning');
stderr_like(sub { $foo_meta->add_attribute(d => (clearer => 'clear_d')) },
- qr/^You cannot overwrite a locally defined method \(clear_d\) with an accessor/, 'clearer overriding gives proper warning');
+ qr/^You are overwriting a locally defined method \(clear_d\) with an accessor/, 'clearer overriding gives proper warning');
stderr_like(sub { $foo_meta->add_attribute(e => (is => 'rw')) },
- qr/^You cannot overwrite a locally defined method \(e\) with an accessor/, 'accessor overriding gives proper warning');
+ qr/^You are overwriting a locally defined method \(e\) with an accessor/, 'accessor overriding gives proper warning');