Commit | Line | Data |
5d9d20f3 |
1 | package Moose::Cookbook::Roles::ApplicationToInstance; |
9a823f26 |
2 | |
daa0fd7d |
3 | # ABSTRACT: Applying a role to an object instance |
4 | |
5 | __END__ |
6 | |
9a823f26 |
7 | =pod |
8 | |
5547fba7 |
9 | =begin testing-SETUP |
c79239a2 |
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 | |
5547fba7 |
30 | =end testing-SETUP |
c79239a2 |
31 | |
9a823f26 |
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 | |
c79239a2 |
53 | $employee->work($work); |
9a823f26 |
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, |
c8b8d92f |
91 | -alias => { assign_work => 'get_off_your_lazy_behind' }, |
9a823f26 |
92 | ); |
93 | |
706d2d37 |
94 | We saw examples of how method exclusion and alias working in |
95 | L<Moose::Cookbook::Roles::Restartable_AdvancedComposition>. |
9a823f26 |
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 | |
c79239a2 |
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 | |
9a823f26 |
129 | =cut |