From: Stevan Little Date: Fri, 27 Jun 2008 00:11:56 +0000 (+0000) Subject: fixing the handles stuff so that it works cleanly for MX::DBIC; X-Git-Tag: 0_55~87 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d3e7fe851abd8b0bca683f3d22e0b04cac24a25a;p=gitmo%2FMoose.git fixing the handles stuff so that it works cleanly for MX::DBIC; --- diff --git a/Changes b/Changes index 42ff956..f6de790 100644 --- a/Changes +++ b/Changes @@ -25,6 +25,8 @@ Revision history for Perl extension Moose * Moose::Meta::Attribute - added support for meta_attr->does("ShortAlias") (sartak) - added tests for this (sartak) + - moved the bulk of the `handles` handling to the new + install_delegation method (Stevan) * Moose::Object - Added BUILDARGS, a new step in new() diff --git a/lib/Moose/Meta/Attribute.pm b/lib/Moose/Meta/Attribute.pm index a3eef3c..353dd7d 100644 --- a/lib/Moose/Meta/Attribute.pm +++ b/lib/Moose/Meta/Attribute.pm @@ -506,67 +506,68 @@ sub accessor_metaclass { 'Moose::Meta::Method::Accessor' } sub install_accessors { my $self = shift; $self->SUPER::install_accessors(@_); + $self->install_delegation if $self->has_handles; + return; +} - if ($self->has_handles) { +sub install_delegation { + my $self = shift; - # NOTE: - # Here we canonicalize the 'handles' option - # this will sort out any details and always - # return an hash of methods which we want - # to delagate to, see that method for details - my %handles = $self->_canonicalize_handles(); - - # find the accessor method for this attribute - my $accessor = $self->get_read_method_ref; - # then unpack it if we need too ... - $accessor = $accessor->body if blessed $accessor; - - # install the delegation ... - my $associated_class = $self->associated_class; - foreach my $handle (keys %handles) { - my $method_to_call = $handles{$handle}; - my $class_name = $associated_class->name; - my $name = "${class_name}::${handle}"; - - (!$associated_class->has_method($handle)) - || confess "You cannot overwrite a locally defined method ($handle) with a delegation"; + # NOTE: + # Here we canonicalize the 'handles' option + # this will sort out any details and always + # return an hash of methods which we want + # to delagate to, see that method for details + my %handles = $self->_canonicalize_handles(); + + # find the accessor method for this attribute + my $accessor = $self->get_read_method_ref; + # then unpack it if we need too ... + $accessor = $accessor->body if blessed $accessor; + + # install the delegation ... + my $associated_class = $self->associated_class; + foreach my $handle (keys %handles) { + my $method_to_call = $handles{$handle}; + my $class_name = $associated_class->name; + my $name = "${class_name}::${handle}"; + + (!$associated_class->has_method($handle)) + || confess "You cannot overwrite a locally defined method ($handle) with a delegation"; - # NOTE: - # handles is not allowed to delegate - # any of these methods, as they will - # override the ones in your class, which - # is almost certainly not what you want. + # NOTE: + # handles is not allowed to delegate + # any of these methods, as they will + # override the ones in your class, which + # is almost certainly not what you want. - # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something - #cluck("Not delegating method '$handle' because it is a core method") and - next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle); + # FIXME warn when $handle was explicitly specified, but not if the source is a regex or something + #cluck("Not delegating method '$handle' because it is a core method") and + next if $class_name->isa("Moose::Object") and $handle =~ /^BUILD|DEMOLISH$/ || Moose::Object->can($handle); - if ('CODE' eq ref($method_to_call)) { - $associated_class->add_method($handle => Class::MOP::subname($name, $method_to_call)); - } - else { - # NOTE: - # we used to do a goto here, but the - # goto didn't handle failure correctly - # (it just returned nothing), so I took - # that out. However, the more I thought - # about it, the less I liked it doing - # the goto, and I prefered the act of - # delegation being actually represented - # in the stack trace. - # - SL - $associated_class->add_method($handle => Class::MOP::subname($name, sub { - my $proxy = (shift)->$accessor(); - (defined $proxy) - || confess "Cannot delegate $handle to $method_to_call because " . - "the value of " . $self->name . " is not defined"; - $proxy->$method_to_call(@_); - })); - } + if ('CODE' eq ref($method_to_call)) { + $associated_class->add_method($handle => Class::MOP::subname($name, $method_to_call)); } - } - - return; + else { + # NOTE: + # we used to do a goto here, but the + # goto didn't handle failure correctly + # (it just returned nothing), so I took + # that out. However, the more I thought + # about it, the less I liked it doing + # the goto, and I prefered the act of + # delegation being actually represented + # in the stack trace. + # - SL + $associated_class->add_method($handle => Class::MOP::subname($name, sub { + my $proxy = (shift)->$accessor(); + (defined $proxy) + || confess "Cannot delegate $handle to $method_to_call because " . + "the value of " . $self->name . " is not defined"; + $proxy->$method_to_call(@_); + })); + } + } } # private methods to help delegation ... @@ -691,6 +692,8 @@ will behave just as L does. =item B +=item B + =item B =item B