use warnings;
use MRO::Compat;
-use Scalar::Util 'blessed';
+use Scalar::Util qw/blessed weaken/;
use Carp 'confess';
sub new {
my %args = @_;
my $instance = bless {}, $class;
- for my $attribute ($class->meta->attributes) {
- my $key = $attribute->init_arg;
+ for my $attribute (values %{ $class->meta->get_attribute_map }) {
+ my $from = $attribute->init_arg;
+ my $key = $attribute->name;
my $default;
- if (!exists($args{$key})) {
- if (exists($attribute->{default})) {
- unless ($attribute->{lazy}) {
- if (ref($attribute->{default}) eq 'CODE') {
- $instance->{$key} = $attribute->{default}->();
- Scalar::Util::weaken($instance->{$key})
- if $attribute->{weak_ref};
- }
- else {
- $instance->{$key} = $attribute->{default};
- Scalar::Util::weaken($instance->{$key})
- if $attribute->{weak_ref};
- }
+ if (!exists($args{$from})) {
+ if ($attribute->has_default || $attribute->has_builder) {
+ unless ($attribute->is_lazy) {
+ my $default = $attribute->default;
+ my $builder = $attribute->builder;
+ my $value = $attribute->has_builder
+ ? $instance->$builder
+ : ref($default) eq 'CODE'
+ ? $default->()
+ : $default;
+
+ $attribute->verify_type_constraint($value)
+ if $attribute->has_type_constraint;
+
+ $instance->{$key} = $value;
+
+ weaken($instance->{$key})
+ if ref($instance->{$key}) && $attribute->is_weak_ref;
}
}
else {
- if ($attribute->{required}) {
- confess "Attribute '$attribute->{name}' is required";
+ if ($attribute->is_required) {
+ confess "Attribute (".$attribute->name.") is required";
}
}
}
- if (exists($args{$key})) {
- $instance->{$key} = $args{$key};
- Scalar::Util::weaken($instance->{$key})
- if $attribute->{weak_ref};
+ if (exists($args{$from})) {
+ $attribute->verify_type_constraint($args{$from})
+ if $attribute->has_type_constraint;
+
+ $instance->{$key} = $args{$from};
+
+ weaken($instance->{$key})
+ if ref($instance->{$key}) && $attribute->is_weak_ref;
- if ($attribute->{trigger}) {
- $attribute->{trigger}->($instance, $args{$key}, $attribute);
+ if ($attribute->has_trigger) {
+ $attribute->trigger->($instance, $args{$from}, $attribute);
}
}
}