requires => {
'Scalar::Util' => '1.18',
'Carp' => '0',
- 'Class::MOP' => '0.22',
+ 'Class::MOP' => '0.25',
'Sub::Name' => '0.02',
'UNIVERSAL::require' => '0',
'Sub::Exporter' => '0', # update this when rjbs releases
- keywords are now exported with Sub::Exporter
thanks chansen for this commit
+ * Moose::Meta::Class
+ - due to changes in Class::MOP, we had to change
+ construct_instance (for the better)
+
+ * Moose::Meta::Attribute
+ - due to changes in Class::MOP, we had to add the
+ initialize_instance_slot method (it's a good thing)
+
0.04 Sun. April 16th, 2006
* Moose::Role
- Roles can now consume other roles
$meta = $class->meta();
(blessed($meta) && $meta->isa('Moose::Meta::Class'))
|| confess "Whoops, not møøsey enough";
- ($meta->attribute_metaclass->isa('Moose::Meta::Attribute'))
- || confess "Attribute metaclass must be a subclass of Moose::Meta::Attribute";
}
else {
$meta = Moose::Meta::Class->initialize($class);
my ($name, %options) = @_;
if ($options{metaclass}) {
_load_all_classes($options{metaclass});
- ($options{metaclass}->isa('Moose::Meta::Attribute'))
- || confess "Custom attribute metaclass must be a subclass of Moose::Meta::Attribute";
$meta->add_attribute($options{metaclass}->new($name, %options));
}
else {
$class->SUPER::new($name, %options);
}
+sub initialize_instance_slot {
+ my ($self, $class, $instance, $params) = @_;
+ my $init_arg = $self->init_arg();
+ # try to fetch the init arg from the %params ...
+ my $val;
+ if (exists $params->{$init_arg}) {
+ $val = $params->{$init_arg};
+ }
+ else {
+ # skip it if it's lazy
+ return if $self->is_lazy;
+ # and die if it's required and doesn't have a default value
+ confess "Attribute (" . $self->name . ") is required"
+ if $self->is_required && !$self->has_default;
+ }
+ # if nothing was in the %params, we can use the
+ # attribute's default value (if it has one)
+ if (!defined $val && $self->has_default) {
+ $val = $self->default($instance);
+ }
+ if (defined $val) {
+ if ($self->has_type_constraint) {
+ if ($self->should_coerce && $self->type_constraint->has_coercion) {
+ $val = $self->type_constraint->coercion->coerce($val);
+ }
+ (defined($self->type_constraint->check($val)))
+ || confess "Attribute (" . $self->name . ") does not pass the type contraint with '$val'";
+ }
+ }
+ $instance->{$self->name} = $val;
+ if (defined $val && $self->is_weak_ref) {
+ weaken($instance->{$self->name});
+ }
+}
+
sub generate_accessor_method {
my ($self, $attr_name) = @_;
my $value_name = $self->should_coerce ? '$val' : '$_[1]';
=item B<new>
+=item B<initialize_instance_slot>
+
=item B<generate_accessor_method>
=item B<generate_writer_method>
my ($class, %params) = @_;
my $self = $class->SUPER::new_object(%params);
foreach my $attr ($class->compute_all_applicable_attributes()) {
- next unless $params{$attr->name} && $attr->has_trigger;
+ next unless $params{$attr->name} && $attr->can('has_trigger') && $attr->has_trigger;
$attr->trigger->($self, $params{$attr->name});
}
return $self;
my ($class, %params) = @_;
my $instance = $params{'__INSTANCE__'} || {};
foreach my $attr ($class->compute_all_applicable_attributes()) {
- my $init_arg = $attr->init_arg();
- # try to fetch the init arg from the %params ...
- my $val;
- if (exists $params{$init_arg}) {
- $val = $params{$init_arg};
- }
- else {
- # skip it if it's lazy
- next if $attr->is_lazy;
- # and die if it's required and doesn't have a default value
- confess "Attribute (" . $attr->name . ") is required"
- if $attr->is_required && !$attr->has_default;
- }
- # if nothing was in the %params, we can use the
- # attribute's default value (if it has one)
- if (!defined $val && $attr->has_default) {
- $val = $attr->default($instance);
- }
- if (defined $val) {
- if ($attr->has_type_constraint) {
- if ($attr->should_coerce && $attr->type_constraint->has_coercion) {
- $val = $attr->type_constraint->coercion->coerce($val);
- }
- (defined($attr->type_constraint->check($val)))
- || confess "Attribute (" . $attr->name . ") does not pass the type contraint with '$val'";
- }
- }
- $instance->{$attr->name} = $val;
- if (defined $val && $attr->is_weak_ref) {
- weaken($instance->{$attr->name});
- }
+ $attr->initialize_instance_slot($class, $instance, \%params)
}
return $instance;
}
package Foo::Meta::Attribute;
use strict;
use warnings;
+ use Moose;
- use base 'Moose::Meta::Attribute';
+ extends 'Moose::Meta::Attribute';
- sub new {
- my $class = shift;
- $class->SUPER::new(@_, (is => 'rw', isa => 'Foo'));
- }
+ around 'new' => sub {
+ my $next = shift;
+ my $self = shift;
+ my $name = shift;
+ $next->($self, $name, (is => 'rw', isa => 'Foo'), @_);
+ };
package Foo;
use strict;
package Bar::Meta::Attribute;
use strict;
use warnings;
+ use Moose;
- use base 'Class::MOP::Attribute';
+ extends 'Class::MOP::Attribute';
package Bar;
use strict;
use warnings;
use Moose;
- ::dies_ok {
+ ::lives_ok {
has 'bar' => (metaclass => 'Bar::Meta::Attribute');
- } '... the attribute metaclass must be a subclass of Moose::Meta::Attribute';
+ } '... the attribute metaclass need not be a Moose::Meta::Attribute as long as it behaves';
}
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 16;
+use Test::Exception;
+
+BEGIN {
+ use_ok('Moose');
+}
+
+{
+ package My::Meta::Class;
+ use strict;
+ use warnings;
+ use Moose;
+
+ extends 'Moose::Meta::Class';
+}
+
+my $anon = My::Meta::Class->create_anon_class();
+isa_ok($anon, 'My::Meta::Class');
+isa_ok($anon, 'Moose::Meta::Class');
+isa_ok($anon, 'Class::MOP::Class');
+
+{
+ package My::Meta::Attribute::DefaultReadOnly;
+ use strict;
+ use warnings;
+ use Moose;
+
+ extends 'Moose::Meta::Attribute';
+
+ around 'new' => sub {
+ my $next = shift;
+ my $self = shift;
+ my $name = shift;
+ $next->($self, $name, (is => 'ro'), @_);
+ };
+}
+
+{
+ my $attr = My::Meta::Attribute::DefaultReadOnly->new('foo');
+ isa_ok($attr, 'My::Meta::Attribute::DefaultReadOnly');
+ isa_ok($attr, 'Moose::Meta::Attribute');
+ isa_ok($attr, 'Class::MOP::Attribute');
+
+ ok($attr->has_reader, '... the attribute has a reader (as expected)');
+ ok(!$attr->has_writer, '... the attribute does not have a writer (as expected)');
+ ok(!$attr->has_accessor, '... the attribute does not have an accessor (as expected)');
+}
+
+{
+ my $attr = My::Meta::Attribute::DefaultReadOnly->new('foo', (is => 'rw'));
+ isa_ok($attr, 'My::Meta::Attribute::DefaultReadOnly');
+ isa_ok($attr, 'Moose::Meta::Attribute');
+ isa_ok($attr, 'Class::MOP::Attribute');
+
+ ok(!$attr->has_reader, '... the attribute does not have a reader (as expected)');
+ ok(!$attr->has_writer, '... the attribute does not have a writer (as expected)');
+ ok($attr->has_accessor, '... the attribute does have an accessor (as expected)');
+}
+