Rename Roles::Recipe2 to Roles::Restartable_AdvancedComposition
[gitmo/Moose.git] / lib / Moose / Cookbook / Roles / Recipe3.pod
CommitLineData
c79239a2 1package Moose::Cookbook::Roles::Recipe3;
9a823f26 2
daa0fd7d 3# ABSTRACT: Applying a role to an object instance
4
5__END__
6
7package Moose::Cookbook::Roles::Recipe3;
8
9a823f26 9=pod
10
5547fba7 11=begin testing-SETUP
c79239a2 12
13{
14 # Not in the recipe, but needed for writing tests.
15 package Employee;
16
17 use Moose;
18
19 has 'name' => (
20 is => 'ro',
21 isa => 'Str',
22 required => 1,
23 );
24
25 has 'work' => (
26 is => 'rw',
27 isa => 'Str',
28 predicate => 'has_work',
29 );
30}
31
5547fba7 32=end testing-SETUP
c79239a2 33
9a823f26 34=head1 SYNOPSIS
35
36 package MyApp::Role::Job::Manager;
37
38 use List::Util qw( first );
39
40 use Moose::Role;
41
42 has 'employees' => (
43 is => 'rw',
44 isa => 'ArrayRef[Employee]',
45 );
46
47 sub assign_work {
48 my $self = shift;
49 my $work = shift;
50
51 my $employee = first { !$_->has_work } @{ $self->employees };
52
53 die 'All my employees have work to do!' unless $employee;
54
c79239a2 55 $employee->work($work);
9a823f26 56 }
57
58 package main;
59
60 my $lisa = Employee->new( name => 'Lisa' );
61 MyApp::Role::Job::Manager->meta->apply($lisa);
62
63 my $homer = Employee->new( name => 'Homer' );
64 my $bart = Employee->new( name => 'Bart' );
65 my $marge = Employee->new( name => 'Marge' );
66
67 $lisa->employees( [ $homer, $bart, $marge ] );
68 $lisa->assign_work('mow the lawn');
69
70=head1 DESCRIPTION
71
72In this recipe, we show how a role can be applied to an object. In
73this specific case, we are giving an employee managerial
74responsibilities.
75
76Applying a role to an object is simple. The L<Moose::Meta::Role>
77object provides an C<apply> method. This method will do the right
78thing when given an object instance.
79
80 MyApp::Role::Job::Manager->meta->apply($lisa);
81
82We could also use the C<apply_all_roles> function from L<Moose::Util>.
83
84 apply_all_roles( $person, MyApp::Role::Job::Manager->meta );
85
86The main advantage of using C<apply_all_roles> is that it can be used
87to apply more than one role at a time.
88
89We could also pass parameters to the role we're applying:
90
91 MyApp::Role::Job::Manager->meta->apply(
92 $lisa,
c8b8d92f 93 -alias => { assign_work => 'get_off_your_lazy_behind' },
9a823f26 94 );
95
706d2d37 96We saw examples of how method exclusion and alias working in
97L<Moose::Cookbook::Roles::Restartable_AdvancedComposition>.
9a823f26 98
99=head1 CONCLUSION
100
101Applying a role to an object instance is a useful tool for adding
102behavior to existing objects. In our example, it is effective used to
103model a promotion.
104
105It can also be useful as a sort of controlled monkey-patching for
106existing code, particularly non-Moose code. For example, you could
107create a debugging role and apply it to an object at runtime.
108
c79239a2 109=begin testing
110
111{
112 my $lisa = Employee->new( name => 'Lisa' );
113 MyApp::Role::Job::Manager->meta->apply($lisa);
114
115 my $homer = Employee->new( name => 'Homer' );
116 my $bart = Employee->new( name => 'Bart' );
117 my $marge = Employee->new( name => 'Marge' );
118
119 $lisa->employees( [ $homer, $bart, $marge ] );
120 $lisa->assign_work('mow the lawn');
121
122 ok( $lisa->does('MyApp::Role::Job::Manager'),
123 'lisa now does the manager role' );
124
125 is( $homer->work, 'mow the lawn',
126 'homer was assigned a task by lisa' );
127}
128
129=end testing
130
9a823f26 131=cut