b81c9f4e52d5ef47c653dcfa1f9b1b1c8bad08ec
[gitmo/Moose-OldDocs.git] / lib / Moose / Cookbook / Roles / Recipe3.pod
1 package Moose::Cookbook::Roles::Recipe3;
2
3 # ABSTRACT: Applying a role to an object instance
4
5 __END__
6
7 package Moose::Cookbook::Roles::Recipe3;
8
9 =pod
10
11 =begin testing-SETUP
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
32 =end testing-SETUP
33
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
55       $employee->work($work);
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
72 In this recipe, we show how a role can be applied to an object. In
73 this specific case, we are giving an employee managerial
74 responsibilities.
75
76 Applying a role to an object is simple. The L<Moose::Meta::Role>
77 object provides an C<apply> method. This method will do the right
78 thing when given an object instance.
79
80   MyApp::Role::Job::Manager->meta->apply($lisa);
81
82 We 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
86 The main advantage of using C<apply_all_roles> is that it can be used
87 to apply more than one role at a time.
88
89 We could also pass parameters to the role we're applying:
90
91   MyApp::Role::Job::Manager->meta->apply(
92       $lisa,
93       -alias => { assign_work => 'get_off_your_lazy_behind' },
94   );
95
96 We saw examples of how method exclusion and alias working in L<roles
97 recipe 2|Moose::Cookbook::Roles::Recipe2>.
98
99 =head1 CONCLUSION
100
101 Applying a role to an object instance is a useful tool for adding
102 behavior to existing objects. In our example, it is effective used to
103 model a promotion.
104
105 It can also be useful as a sort of controlled monkey-patching for
106 existing code, particularly non-Moose code. For example, you could
107 create a debugging role and apply it to an object at runtime.
108
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
131 =cut