Hey all,
I have been trying to get callback methods working in Moose for a while now and
I haven't found anything in the documentation that can help me out. I'm trying
to find how to use a callback method with arguments inside a Moose object.
I first hit this issue while using File::Find, which needs a callback function
to use for each file or directory it finds. After some tinkering, I found that
the non-OO version:
find({wanted => \&my_callback}, $directory_name);
can be made to work inside a Moose class by making this change:
find({wanted => sub {$self->my_callback}}, $directory_name);
The method 'my_callback' needs to be modified with "my $self = shift;" as one
would expect, of course.
There are situations where this doesn't work for me though, specifically with
the XML::Twig module. XML elements are passed through handlers with a syntax
similar to File::Find. Instead of {wanted => \&my_callback}, it's a hash of
element names and the name of the handler to use for that element:
my $parser = XML::Twig->new(
twig_roots => {
'title' => \&title_handler,
'description' => \&description_handler,
'item' => \&item_handler,
},
);
I've got some existing XML-parsing code that works from a flat script, but
making it Moosier is proving problematic. I've gone through a bunch of
permutations of calling callback methods and none of these permutations seem to
work:
'title' => sub {$self->title_handler},
'title' => 'title_handler',
'title' => ['title_handler'],
'title' => $self->{'title_handler'},
'title' => $self->{['title_handler']},
I've even tried being clever and defining a CodeRef wrapper around the callback
method:
has 'callback_wrapper' => (
is => 'rw',
isa => 'CodeRef',
default => sub {my ($self)=shift; sub{$self->title_handler;}},
);
The issue seems to be that the arguments to be given to the callback are
missing. Based on the XML::Twig docs, handlers are passed a self-referencing
object called a twig and the element to handle, like so:
sub title_handler {
my ($twig, $element) = @_;
return unless ('rss' eq lc($element->parent->tag));
# Do something with $element
return;
}
I've added "my $self = shift;" to the title_handler() method, but in every case
I've tested both $twig and $element are undefined, so the rest of the handler
logic throws an error. Is there any good documentation or advice that can tell
me what I'm doing wrong? Thanks.
Toby