AUTOLOAD method
"Vadim O. Ustiansky" <[email protected]>
| Newsgroups | gmane.comp.web.mason.devel |
|---|---|
| Message-ID | <[email protected]> |
Dear developers,
I would like Mason to have the possibility to handle non-existent
methods in a way, similar to perl's AUTOLOAD. In particular one
may want to be able to write components like the following:
...
% $m->comp('SELF:foo');
% $m->comp('SELF:bar');
...
<%method AUTOLOAD>
<%perl>
my $method_name = $m->autoload();
if($method_name eq 'foo'){
# handle call SELF:foo
}elsif($method_name eq 'bar'){
# handle call SELF:bar
}
</%perl>
</%method>
The attached patch seems to implement this feature.
I would like to here your opinion on this topic.
--
Yours sincerely,
Vadim.
p4
(text/plain, 5.4 KB)
diff -ur mason.orig/dist/lib/HTML/Mason/Component.pm mason.4/dist/lib/HTML/Mason/Component.pm
--- mason.orig/dist/lib/HTML/Mason/Component.pm 2004-05-25 17:33:49.000000000 +0400
+++ mason.4/dist/lib/HTML/Mason/Component.pm 2004-06-05 12:57:15.000000000 +0400
@@ -250,8 +250,12 @@
sub call_method {
my ($self,$name,@args) = @_;
my $method;
+ my $m = HTML::Mason::Request->instance();
if ($self->_locate_inherited('methods',$name,\$method)) {
- HTML::Mason::Request->instance->comp({base_comp=>$self},$method,@args);
+ $m->comp({base_comp=>$self},$method,@args);
+ } elsif ($m->use_autoload() && $self->_locate_inherited('methods','AUTOLOAD',\$method)) {
+ $m->_set_autoload($name);
+ $m->comp({base_comp=>$self},$method,@args);
} else {
error "no method '$name' for component " . $self->title;
}
@@ -263,8 +267,12 @@
sub scall_method {
my ($self,$name,@args) = @_;
my $method;
+ my $m = HTML::Mason::Request->instance();
if ($self->_locate_inherited('methods',$name,\$method)) {
- HTML::Mason::Request->instance->scomp({base_comp=>$self},$method,@args);
+ $m->scomp({base_comp=>$self},$method,@args);
+ } elsif ($m->use_autoload() && $self->_locate_inherited('methods','AUTOLOAD',\$method)) {
+ $m->_set_autoload($name);
+ $m->comp({base_comp=>$self},$method,@args);
} else {
error "no method '$name' for component " . $self->title;
}
diff -ur mason.orig/dist/lib/HTML/Mason/Interp.pm mason.4/dist/lib/HTML/Mason/Interp.pm
--- mason.orig/dist/lib/HTML/Mason/Interp.pm 2004-05-25 17:33:49.000000000 +0400
+++ mason.4/dist/lib/HTML/Mason/Interp.pm 2004-06-05 13:22:09.000000000 +0400
@@ -115,6 +115,7 @@
[ error_mode => { type => SCALAR } ],
[ max_recurse => { type => SCALAR } ],
[ out_method => { type => SCALARREF | CODEREF } ],
+ [ use_autoload => { type => SCALAR | UNDEF } ],
]
},
);
diff -ur mason.orig/dist/lib/HTML/Mason/Request.pm mason.4/dist/lib/HTML/Mason/Request.pm
--- mason.orig/dist/lib/HTML/Mason/Request.pm 2004-05-25 17:33:49.000000000 +0400
+++ mason.4/dist/lib/HTML/Mason/Request.pm 2004-06-05 13:07:34.000000000 +0400
@@ -127,6 +127,10 @@
public => 0,
},
+ use_autoload =>
+ { parse => 'boolean', type => SCALAR|UNDEF, optional => 1,
+ descr => "Whether AUTOLOAD methods available" },
+
);
__PACKAGE__->contained_objects
@@ -145,9 +149,11 @@
error_format
error_mode
max_recurse
- out_method ); }
+ out_method
+ use_autoload ); }
use HTML::Mason::MethodMaker
( read_only => [ qw( count
+ autoload
dhandler_arg
interp
parent_request
@@ -167,6 +173,7 @@
my $self = $class->SUPER::new(@_);
%$self = (%$self, buffer_stack => undef,
+ autoload => undef,
count => 0,
dhandler_arg => undef,
execd => 0,
@@ -271,6 +278,12 @@
return defined $self->{dhandler_name} and length $self->{dhandler_name};
}
+sub _set_autoload
+{
+ my $self = shift;
+ $self->{autoload} = shift;
+}
+
sub alter_superclass
{
my $self = shift;
@@ -927,8 +940,14 @@
my ($owner_path,$method_name) = split(':',$path,2);
my $owner_comp = $self->fetch_comp($owner_path)
or error "could not find component for path '$owner_path'\n";
- $owner_comp->_locate_inherited('methods',$method_name,\$method_comp)
- or error "no method '$method_name' for component " . $owner_comp->title;
+ unless ($owner_comp->_locate_inherited('methods',$method_name,\$method_comp)) {
+ if ($self->use_autoload() && $self->{_fetch_autoload_method} &&
+ $owner_comp->_locate_inherited('methods','AUTOLOAD',\$method_comp)) {
+ $self->_set_autoload($method_name);
+ } else {
+ error "no method '$method_name' for component " . $owner_comp->title;
+ }
+ }
return $method_comp;
}
@@ -1059,9 +1078,12 @@
#
my $path;
if (!ref($comp)) {
+ my $store = $self->{_fetch_autoload_method};
+ $self->{_fetch_autoload_method} = 1;
$path = $comp;
$comp = $self->fetch_comp($path)
or error "could not find component for path '$path'\n";
+ $self->{_fetch_autoload_method} = $store;
}
#
diff -ur mason.orig/dist/t/09-component.t mason.4/dist/t/09-component.t
--- mason.orig/dist/t/09-component.t 2004-05-25 17:33:50.000000000 +0400
+++ mason.4/dist/t/09-component.t 2004-06-05 13:41:48.000000000 +0400
@@ -463,6 +463,28 @@
#------------------------------------------------------------
+ $group->add_test( name => 'autoload_methods',
+ interp_params => { use_autoload => 1 },
+ description => 'Test that AUTOLOAD method works',
+ component => <<'EOF',
+% $m->base_comp()->call_method('foo');
+<& SELF:bar, arg => 1 &>
+
+<%method AUTOLOAD>
+% my $method_name = $m->autoload();
+Called method: <% $method_name %>, <% join(',', @_) %>.
+</%method>
+EOF
+ expect => <<'EOF',
+
+Called method: foo, .
+
+Called method: bar, arg,1.
+EOF
+ );
+
+#------------------------------------------------------------
+
$group->add_test( name => 'modification_read_only_arg',
description => 'Test that read-only argument cannot be modified through @_',
component => <<'EOF',