added test from #62467
[gitmo/MooseX-ClassAttribute.git] / lib / MooseX / ClassAttribute / Trait / Attribute.pm
CommitLineData
63fcc508 1package MooseX::ClassAttribute::Trait::Attribute;
bb70fe3a 2
3use strict;
4use warnings;
5
88b7f2c8 6use namespace::autoclean;
a1ec1ff1 7use Moose::Role;
bb70fe3a 8
a1ec1ff1 9# This is the worst role evar! Really, this should be a subclass,
10# because it overrides a lot of behavior. However, as a subclass it
8e988dc6 11# won't cooperate with _other_ subclasses.
bb70fe3a 12
88b7f2c8 13around '_process_options' => sub {
a1ec1ff1 14 my $orig = shift;
bb70fe3a 15 my $class = shift;
16 my $name = shift;
17 my $options = shift;
18
19 confess 'A class attribute cannot be required'
20 if $options->{required};
21
a1ec1ff1 22 return $class->$orig( $name, $options );
23};
bb70fe3a 24
88b7f2c8 25around attach_to_class => sub {
a1ec1ff1 26 my $orig = shift;
bb70fe3a 27 my $self = shift;
28 my $meta = shift;
29
a1ec1ff1 30 $self->$orig($meta);
bb70fe3a 31
32 $self->_initialize($meta)
33 unless $self->is_lazy();
a1ec1ff1 34};
bb70fe3a 35
88b7f2c8 36around 'detach_from_class' => sub {
a1ec1ff1 37 my $orig = shift;
bb70fe3a 38 my $self = shift;
39 my $meta = shift;
40
41 $self->clear_value($meta);
42
a1ec1ff1 43 $self->$orig($meta);
44};
bb70fe3a 45
88b7f2c8 46sub _initialize {
6048a053 47 my $self = shift;
48 my $metaclass = shift;
bb70fe3a 49
88b7f2c8 50 if ( $self->has_default() ) {
d0785271 51 $self->set_value( undef, $self->default() );
bb70fe3a 52 }
88b7f2c8 53 elsif ( $self->has_builder() ) {
6048a053 54 $self->set_value( undef, $self->_call_builder( $metaclass->name() ) );
bb70fe3a 55 }
56}
57
88b7f2c8 58around 'default' => sub {
a1ec1ff1 59 my $orig = shift;
bb70fe3a 60 my $self = shift;
61
a1ec1ff1 62 my $default = $self->$orig();
bb70fe3a 63
88b7f2c8 64 if ( $self->is_default_a_coderef() ) {
bb70fe3a 65 return $default->( $self->associated_class() );
66 }
67
68 return $default;
a1ec1ff1 69};
bb70fe3a 70
88b7f2c8 71around '_call_builder' => sub {
a1ec1ff1 72 shift;
bb70fe3a 73 my $self = shift;
74 my $class = shift;
75
76 my $builder = $self->builder();
77
78 return $class->$builder()
79 if $class->can( $self->builder );
80
81 confess( "$class does not support builder method '"
82 . $self->builder
83 . "' for attribute '"
84 . $self->name
85 . "'" );
a1ec1ff1 86};
bb70fe3a 87
88b7f2c8 88around 'set_value' => sub {
a1ec1ff1 89 shift;
88b7f2c8 90 my $self = shift;
91 shift; # ignoring instance or class name
92 my $value = shift;
bb70fe3a 93
88b7f2c8 94 $self->associated_class()
95 ->set_class_attribute_value( $self->name() => $value );
a1ec1ff1 96};
bb70fe3a 97
88b7f2c8 98around 'get_value' => sub {
a1ec1ff1 99 shift;
88b7f2c8 100 my $self = shift;
bb70fe3a 101
88b7f2c8 102 return $self->associated_class()
103 ->get_class_attribute_value( $self->name() );
a1ec1ff1 104};
bb70fe3a 105
88b7f2c8 106around 'has_value' => sub {
a1ec1ff1 107 shift;
88b7f2c8 108 my $self = shift;
bb70fe3a 109
88b7f2c8 110 return $self->associated_class()
111 ->has_class_attribute_value( $self->name() );
a1ec1ff1 112};
bb70fe3a 113
88b7f2c8 114around 'clear_value' => sub {
a1ec1ff1 115 shift;
88b7f2c8 116 my $self = shift;
bb70fe3a 117
88b7f2c8 118 return $self->associated_class()
119 ->clear_class_attribute_value( $self->name() );
a1ec1ff1 120};
bb70fe3a 121
619dd6df 122override '_inline_instance_get' => sub {
935982fc 123 my $self = shift;
124
125 return $self->associated_class()
126 ->inline_get_class_slot_value( $self->slots() );
127};
128
619dd6df 129
130override _inline_weaken_value => sub {
131 my $self = shift;
132 my ($instance, $value) = @_;
133 return unless $self->is_weak_ref;
134
135 my $mi = $self->associated_class->get_meta_instance;
136 return (
137 $self->associated_class->inline_weaken_class_slot_value( $self->slots(), $value ),
138 'if ref ' . $value . ';',
139 );
140};
141
142override '_inline_instance_set' => sub {
935982fc 143 my $self = shift;
144 shift;
145 my $value = shift;
146
147 my $meta = $self->associated_class();
148
149 my $code
150 = $meta->inline_set_class_slot_value( $self->slots(), $value ) . ";";
935982fc 151
152 return $code;
153};
154
619dd6df 155override '_inline_instance_has' => sub {
935982fc 156 my $self = shift;
157
158 return $self->associated_class()
159 ->inline_is_class_slot_initialized( $self->slots() );
160};
161
619dd6df 162override '_inline_clear_value' => sub {
935982fc 163 my $self = shift;
164
165 return $self->associated_class()
166 ->inline_deinitialize_class_slot( $self->slots() );
167};
168
bb70fe3a 1691;
7a4a3b1e 170
0d0bf8c3 171# ABSTRACT: A trait for class attributes
172
7a4a3b1e 173__END__
174
175=pod
176
7a4a3b1e 177=head1 DESCRIPTION
178
179This role modifies the behavior of class attributes in various
180ways. It really should be a subclass of C<Moose::Meta::Attribute>, but
181if it were then it couldn't be combined with other attribute
182metaclasses, like C<MooseX::AttributeHelpers>.
183
184There are no new public methods implemented by this role. All it does
185is change the behavior of a number of existing methods.
186
7a4a3b1e 187=head1 BUGS
188
189See L<MooseX::ClassAttribute> for details.
190
7a4a3b1e 191=cut