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

Mojo::Base::with_roles patch #1120

Merged
merged 1 commit into from Aug 10, 2017
Merged

Conversation

dotandimet
Copy link
Contributor

Summary

Add with_roles method to Mojo::Base, per the specs described here:
https://irclog.perlgeek.de/mojo/2017-08-08#i_14984146

Motivation

Allow multiple developers to extend key Mojolicious classes (Test::Mojo, Mojo::UserAgent, etc)
using Role::Tiny (optional dependency)

References

https://irclog.perlgeek.de/mojo/2017-08-08#i_14984146

lib/Mojo/Base.pm Outdated
@@ -61,6 +61,10 @@ sub attr {
}
}

sub can_roles {
return !!(eval 'require Role::Tiny' && $Role::Tiny::VERSION >= 2.000005);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a constant and the can_roles method is just for exposure outside of the class. C.f. https://github.com/kraih/mojo/blob/be50b20ae6c80df78a2594fdd198c19364f649ad/lib/Mojo/IOLoop/Client.pm#L13-L15

lib/Mojo/Base.pm Outdated
@@ -101,6 +105,16 @@ sub tap {
return $self;
}

sub with_roles {
if ($_[0]->can_roles()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Within the class, it should use the constant (see above), since this will be constant folded at compile time and not introduce overhead on each with_roles call

lib/Mojo/Base.pm Outdated
@@ -61,6 +61,10 @@ sub attr {
}
}

sub can_roles {
return !!(eval 'require Role::Tiny' && $Role::Tiny::VERSION >= 2.000005);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not consistent with our other optional dependencies.

lib/Mojo/Base.pm Outdated
@@ -101,6 +105,16 @@ sub tap {
return $self;
}

sub with_roles {
if ($_[0]->can_roles()) {
Carp::croak "class and roles must be package names" if !!grep { ref $_ } @_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a good reason that argument validation is required here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_class_with_roles will error if anything other than a valid role name is passed, so probably not needed

Copy link
Contributor

@Grinnz Grinnz Aug 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be worthwhile checking that the invocant is not an object though, there's no explicit check for that in Role::Tiny and it could lead to weird things being loaded based on object stringification

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change it to only check the invocant.

Copy link
Member

@kraih kraih Aug 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not something we normally do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove it and see how cryptic the error is in the tests...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, my error is nice, but if you try to invoke with_roles on an object, you get a terrifying exception, so I'm fine with that (something like "Can't locate Mojo/RoleTest/Base__WITH__Mojo/RoleTest/LOUD=HASH(0x17e56b0).pm in @inc", or whatever)

lib/Mojo/Base.pm Outdated
return Role::Tiny->create_class_with_roles(@_);
}
else {
Carp::croak "Role::Tiny 2.000005 is required for with_roles method";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really require 2.000005, or would a nicer looking 2.0 work too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend at least 2.000001 for an important fix to created class names. https://rt.cpan.org/Public/Bug/Display.html?id=103310

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change it to 2.000001+

lib/Mojo/Base.pm Outdated

my $roles_ok = Mojo::Base->can_roles()

True if L<Role::Tiny> 2.000005+ is installed and roles are supported in Mojo::Base
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mojo::Base is not a link.

lib/Mojo/Base.pm Outdated
@@ -210,6 +224,13 @@ executed at accessor read time if there's no set value, and gets passed the
current instance of the object as first argument. Accessors can be chained, that
means they return their invocant when they are called with an argument.

=head2 can_roles

my $roles_ok = Mojo::Base->can_roles()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We write my $bool = ... for methods that return booleans.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also missing semicolon.

@@ -27,6 +28,7 @@ OPTIONAL
IO::Socket::Socks 0.64+ ($socks)
IO::Socket::SSL 1.94+ ($tls)
Net::DNS::Native 0.15+ ($nnr)
Role::Tiny 2.000005+ ($roles)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation.

t/mojo/roles.t Outdated
use Mojo::Base -strict;
use Test::More;

plan skip_all => "Role::Tiny required for roles" unless Mojo::Base->can_roles;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inconsistent with other tests for optional dependencies.

t/mojo/roles.t Outdated

# First test derived from sri's comment here:
# https://github.com/kraih/mojo/pull/1118#issuecomment-320930345
# TODO: make this a subtest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use these kinda comments.

t/mojo/roles.t Outdated
package Test::Mojo::Role::Location;

use Role::Tiny;
use Test::More; # for is()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used twice.

t/mojo/roles.t Outdated
$t->get_ok('http://mojolicio.us')
->status_is(301)
->location_is('http://mojolicious.org/')
->or(sub { diag 'doh!' });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good test case, keep it simple.

t/mojo/roles.t Outdated

use Test::Mojo;

plan tests => 3;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't use plans.

t/mojo/roles.t Outdated
plan tests => 3;

my $t = Test::Mojo->with_roles('Test::Mojo::Role::Location')->new();
$t->get_ok('http://mojolicio.us')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests shouldn't require an internet connection.

@kraih
Copy link
Member

kraih commented Aug 10, 2017

Don't forget to squash your commits.

lib/Mojo/Base.pm Outdated
@@ -15,6 +15,10 @@ use IO::Handle ();
my $NAME
= eval { require Sub::Util; Sub::Util->can('set_subname') } || sub { $_[1] };

# Role support requires Role::Tiny 2.000001+
use constant ROLES =>
!!(eval 'require Role::Tiny' && $Role::Tiny::VERSION >= 2.000001);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not eval 'use Role::Tiny 2.000001 (); 1';
like at https://github.com/kraih/mojo/blob/master/lib/Mojo/IOLoop/TLS.pm#L11 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the best method would be eval { require Role::Tiny; Role::Tiny->VERSION('2.000001'); 1 }

String eval is unnecessary for this, and the ->VERSION method (same as used by use) is the correct way to check a module's version.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does look much better.

@@ -27,6 +28,7 @@ OPTIONAL
IO::Socket::Socks 0.64+ ($socks)
IO::Socket::SSL 1.94+ ($tls)
Net::DNS::Native 0.15+ ($nnr)
Role::Tiny 2.000005+ ($roles)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.000001+

t/mojo/roles.t Outdated

BEGIN {
# bail in a BEGIN block, so we can use Role::Tiny in inline classes below
use Test::More;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the use Test::More outside the block and remove the comment.

@@ -27,6 +28,7 @@ OPTIONAL
IO::Socket::Socks 0.64+ ($socks)
IO::Socket::SSL 1.94+ ($tls)
Net::DNS::Native 0.15+ ($nnr)
Role::Tiny 2.000001+ ($roles)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is still wrong.

@dotandimet dotandimet force-pushed the with_roles branch 2 times, most recently from eb3cca3 to 4700660 Compare August 10, 2017 16:45
Support extending Mojo::Base classes with roles, using Role::Tiny
(optional dependency)
@kraih kraih merged commit 492e6c4 into mojolicious:master Aug 10, 2017
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

Successfully merging this pull request may close these issues.

None yet

5 participants