7. Slightly More Modern Perl
package PerkyProfiler::Service::Role::OwnsUri;
use Moose::Role;
requires 'source';
use URI;
sub owns_uri {
my ($self, $uri) = @_;
$uri = URI->new($uri) if not UNIVERSAL::isa( $uri, 'URI' );
my $source = $self->source;
return ( $uri->host() =~ /.$source./i )
}
1;
8. Modern Perl
use MooseX::Declare; use MooseX::MultiMethod;
use Moose::Role;
use URI;
role PerkyProfiler::Service::Role::OwnsUri requires 'source'
{
multi method owns_uri( URI $uri) {
my $source = $self->source;
return ( $uri->host() =~ /.$source./i )
}
}
1;
9. Hate it because it does a lot
Meta Object Protocol
new object system on top of MOP
Several nice web frameworks
functional programming
13. Project
Vending machine
except, instead of vending items it vends ‘identities’
and instead of taking ‘coins’ it takes ‘URL’s
14. Project
Vending machine
except, instead of vending items it vends ‘identities’
and instead of taking ‘coins’ it takes ‘URL’s
and instead of being a ‘machine’ it is a ‘website’
15. Project
Vending machine
except, instead of vending items it vends ‘identities’
and instead of taking ‘coins’ it takes ‘URL’s
and instead of being a ‘machine’ it is a ‘website’
and instead of having states it is ‘stateless’
16. Project
Vending machine
except, instead of vending items it vends ‘identities’
and instead of taking ‘coins’ it takes ‘URL’s
and instead of being a ‘machine’ it is a ‘website’
and instead of having states it is ‘stateless’
...
18. Goals of project
Given a URL
get info about the contributor on that service
comb other services for information on that user
Services chosen
GitHub
Flickr
Twitter
Use CPAN when possible
21. Helpers
Start an app:
catalyst.pl PerkyProfiler
Add a model:
./script/perkyprofiler_create.pl model Profiler
Add a view:
./script/perkyprofiler_create.pl view Main TTSite
22. Incorporating a new Model
package PerkyProfiler::Model::Profiler;
use strict;
use warnings;
use parent 'Catalyst::Model::Adaptor';
__PACKAGE__->config( class => 'PerkyProfiler::Profiler');
23. Use new model
sub index :Path :Args(0) {
my ( $self, $c ) = @_;
...
my $profiler = $c->model('Profiler');
my $entity;
eval {
$entity = $profiler->generate_entity_from_uri($c->req->param('url'));
$profiler->loop_update_entity($entity);
$c->stash->{'entity'} = $entity;
};
if( my $err = $@) {
$c->stash->{'message'} = "Sorry, but an error occured:" . $err->message(); }}
24. Profiler
loop_update_entity
given an entity loops through and updates it
generate_entity_from_uri
Generates a new entity object from a given URI
25. Example Service: Flickr
package PerkyProfiler::Service::Flickr;
use Flickr::Simple2;
use PerkyProfiler::Entity;
use PerkyProfiler::Entity::Attribute;
use Moose;
with 'PerkyProfiler::Service::Role';
has _core => ( isa => 'Flickr::Simple2', is => 'rw');
has key => ( isa => 'Str', is => 'ro' );
has secret => ( isa => 'Str', is => 'ro' );
has _contributed => ( isa => 'Bool', is => 'rw', default => 0 );
26. Moose
“Post Modern” Object System that provides:
roles
declarative definitions
delegation
typing
method modifiers
…and more!
27. Declarative Style Classes Ex
has _core => (
isa => ‘Flickr::Simple2’,
is => ‘rw’,
handles =>
{ entity_from_username => 'get_user_byUsername'
entity_from_url => 'get_user_byUrl ' }
);
28. Declarative Style Class Defs
Simply say what it has, eg, “has key => ( isa => 'Str', is => 'ro' )”
Declare different things:
is - read/write permissions
default - default value, or sub that generates the value
lazy - lazy generation
required
delegated tasks
isa - type
29. Types?
Yes, perl is loosely typed, but Moose checks for you.
It can do:
predefined types like strings, integers, numbers
ref too, eg, ArrayRef[CodeRef] is an array of subs
classes
custom types
30. Custom Types
New types
type ‘two_chars’ => where { defined $_ && length
$_ == 2};
Subtypes
subtype ‘EvenInt’ => as ‘Int’ => where { $_ % 2 + 1}
=> message {“Please provide an even number”}
31. Back to the example
package PerkyProfiler::Service::Flickr;
use Flickr::Simple2;
use PerkyProfiler::Entity;
use PerkyProfiler::Entity::Attribute;
use Moose;
with 'PerkyProfiler::Service::Role';
has _core => ( isa => 'Flickr::Simple2', is => 'rw');
has key => ( isa => 'Str', is => 'ro' );
has secret => ( isa => 'Str', is => 'ro' );
has _contributed => ( isa => 'Bool', is => 'rw', default => 0 );
32. Moose Roles
Roles can be used simply by saying: “with
'PerkyProfiler::Service::Role';”
Roles allow you to define a list of methods that must exist
(an interface)
Roles also allow you to define a list of methods that
cannot exist
Finally roles can provide you with additional functionality
(mixin)
33. New Example: Service::Role
package PerkyProfiler::Service::Role;
use Moose::Role;
with 'PerkyProfiler::Service::Role::UsernameGenerator';
with 'PerkyProfiler::Service::Role::OwnsUri';
requires '_get_user_from_uri';
requires '_get_user_info';
requires 'map_to_entity';
requires 'contributor';
34. Providing a Role
Just `use Moose::Role;`
Roles can consume other Roles
Roles can require subs via requires, eg, requires
‘map_to_entity’
Roles can exclude other roles via excludes, eg, exclude
‘ConflictingRole’
35. Example: Working with Roles
Objects can be introspected for roles
foreach my $service ( $self->_services->gen_iterator->() )
{
if($service->meta->does_role($owns_uri_role))
{
if($service->owns_uri($uri))
{
return $service->entity_from_uri($uri);
}}}
36. What else can Moose do?
Meta everything (Meta attributes, classes, roles)
Anonymous classes
autoboxing with MooseX::Autobox
multimethod dispatching with MooseX::MultiMethod
37. What else does Perl have?
DBIx::Class
Object Relational Mapper
classes are based off tables, but can be reassigned
columns can be custom inflated