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

Reply via email to