Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@jhthorsen
Last active February 14, 2018 16:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jhthorsen/0ad4c5c84661588e89da910a08460e88 to your computer and use it in GitHub Desktop.
Save jhthorsen/0ad4c5c84661588e89da910a08460e88 to your computer and use it in GitHub Desktop.
How to extract methods and attributes
package ClassMeta;
use Mojo::Base -strict;
use Hook::AfterRuntime;
use B::Hooks::EndOfScope;
sub import {
my $class = shift;
my $caller = caller;
my %meta = (ATTRS => {}, METHODS => {});
my %ignore;
after_runtime { $class->_find_attributes($caller, \%meta, \%ignore) };
on_scope_end { $class->_find_methods($caller, \%meta, \%ignore) };
no strict 'refs';
*{"$caller\::$_"} = $meta{$_} for keys %meta;
for my $name (keys %{"$caller\::"}) {
$ignore{$name} = *{"$caller\::$name"}{CODE} if *{"$caller\::$name"}{CODE};
}
}
sub _find_attributes {
my ($class, $caller, $meta, $ignore) = @_;
no strict 'refs';
for my $name (keys %{"$caller\::"}) {
next if $ignore->{$name} or $meta->{METHODS}{$name};
$meta->{ATTRS}{$name} = *{"$caller\::$name"}{CODE} if *{"$caller\::$name"}{CODE};
}
}
sub _find_methods {
my ($class, $caller, $meta, $ignore) = @_;
no strict 'refs';
for my $name (keys %{"$caller\::"}) {
next if $ignore->{$name};
$meta->{METHODS}{$name} = *{"$caller\::$name"}{CODE} if *{"$caller\::$name"}{CODE};
}
}
1;
#!/usr/bin/env perl
use Mojo::Base -strict;
use lib '.';
use MyClass;
for my $name (keys %MyClass::ATTRS) {
warn "attr: $name\n";
}
for my $name (keys %MyClass::METHODS) {
warn "method: $name\n";
}
__END__
The script above will output:
attr: a
attr: b
method: a_and_b
package MyClass;
use Mojo::Base -base;
# Need to use ClassMeta after other modules has exported functions, such as "has"
use ClassMeta;
has a => 1;
has b => 2;
sub a_plus_b { $_[0]->a + $_[0]->b }
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment