Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modified has not used after modifying it via application of a role via begin #3

Open
djerius opened this issue Sep 12, 2022 · 3 comments

Comments

@djerius
Copy link

djerius commented Sep 12, 2022

I'd like to apply a role to a MooX::Press generated class which modifies has. Here's the role:

package VOTable::Order;

use v5.10;

use Moo::Role;
use Moo::_Utils;
use Role::Hooks;

Role::Hooks->after_apply(
    __PACKAGE__,
    sub {
        my $class = $_[1];
        say STDERR "After apply in $class";
        Moo::_Utils::_install_modifier( $class, after => has => sub { say "$class\::has($_[0])" } );
    }
);

1;

And here's the Moo::Xpress class:

package VOTable;

use v5.10;

use strict;
use warnings;

use MooX::Press (
    prefix        => __PACKAGE__,
    'class:Field' => {
        begin => sub {
            my $class = shift;
            Moo::Role->apply_roles_to_package( $class, 'VOTable::Order' );
        },
        has => ['id'],
    },
);

1;

Here's a test class which is equivalent to the above generated one:

package VOTable::Snap;
    use Moo;
    with 'VOTable::Order';
    has id => ( is => 'ro' );
1;

And here's what I get when I load the classes:

$ perl  testlib/lib/perl5/VOTable.pm
After apply in VOTable::Field

$ plx perl  testlib/lib/perl5/VOTable/Snap.pm
After apply in VOTable::Snap
VOTable::Snap::has(id)

I'm guessing it's not finding the modified version of has.

@tobyink
Copy link
Owner

tobyink commented Sep 12, 2022

The way MooX::Press gets a reference to has is:

# I hate this...
$_cached_moo_helper{"$package\::$helpername"} ||= eval sprintf(
   'do { package %s; use Moo%s; my $coderef = \&%s; no Moo%s; $coderef };',
   $package,
   $is_role ? '::Role' : '',
   $helpername,
   $is_role ? '::Role' : '',
);

So yes, it will get a "fresh" copy of has, and not the one you've wrapped.

Not sure what a good solution for this is.

@tobyink
Copy link
Owner

tobyink commented Sep 12, 2022

Perhaps something like:

$_cached_moo_helper{"$package\::$helpername"} ||=
   do { no strict 'refs'; \&{"$package\::$helpername"} } ||
   eval sprintf(
      'do { package %s; use Moo%s; my $coderef = \&%s; no Moo%s; $coderef };',
      $package,
      $is_role ? '::Role' : '',
      $helpername,
      $is_role ? '::Role' : '',
   );

@djerius
Copy link
Author

djerius commented Sep 12, 2022

That works for my case, but unfortunately it breaks tests:

t/91factoryroles-zylite.t ..... Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run 
t/91factoryroles.t ............ Undefined subroutine &MyApp::with called at /tmp/MooX-Press-0.086/lib/MooX/Press.pm line 1842.
BEGIN failed--compilation aborted at t/91factoryroles.t line 21.
t/91factoryroles.t ............ Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants