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