Commit | Line | Data |
826230c2 |
1 | package Moose::Cookbook::Meta::Table_MetaclassTrait; |
c5b9daec |
2 | |
6d84892d |
3 | # ABSTRACT: Adding a "table" attribute as a metaclass trait |
daa0fd7d |
4 | |
5 | __END__ |
c5b9daec |
6 | |
c5b9daec |
7 | |
daa0fd7d |
8 | =pod |
c5b9daec |
9 | |
1910e831 |
10 | =begin testing-SETUP |
11 | |
12 | BEGIN { |
13 | package MyApp::Meta::Class::Trait::HasTable; |
14 | use Moose::Role; |
15 | |
16 | has table => ( |
17 | is => 'rw', |
18 | isa => 'Str', |
19 | ); |
20 | } |
21 | |
22 | =end testing-SETUP |
23 | |
c5b9daec |
24 | =head1 SYNOPSIS |
25 | |
1910e831 |
26 | # in lib/MyApp/Meta/Class/Trait/HasTable.pm |
c5b9daec |
27 | package MyApp::Meta::Class::Trait::HasTable; |
28 | use Moose::Role; |
29 | |
6a7e3999 |
30 | has table => ( |
31 | is => 'rw', |
32 | isa => 'Str', |
33 | ); |
c5b9daec |
34 | |
35 | package Moose::Meta::Class::Custom::Trait::HasTable; |
36 | sub register_implementation { 'MyApp::Meta::Class::Trait::HasTable' } |
37 | |
1910e831 |
38 | # in lib/MyApp/User.pm |
c5b9daec |
39 | package MyApp::User; |
40 | use Moose -traits => 'HasTable'; |
41 | |
fe015af9 |
42 | __PACKAGE__->meta->table('User'); |
c5b9daec |
43 | |
44 | =head1 DESCRIPTION |
45 | |
6d84892d |
46 | In this recipe, we'll create a class metaclass trait which has a "table" |
47 | attribute. This trait is for classes associated with a DBMS table, as one |
48 | might do for an ORM. |
c5b9daec |
49 | |
6d84892d |
50 | In this example, the table name is just a string, but in a real ORM |
51 | the table might be an object describing the table. |
c5b9daec |
52 | |
6d84892d |
53 | =head1 THE METACLASS TRAIT |
c5b9daec |
54 | |
6d84892d |
55 | This really is as simple as the recipe L</SYNOPSIS> shows. The trick is |
56 | getting your classes to use this metaclass, and providing some sort of sugar |
57 | for declaring the table. This is covered in |
97da20ef |
58 | L<Moose::Cookbook::Extending::Debugging_BaseClassRole>, which shows how to |
59 | make a module like C<Moose.pm> itself, with sugar like C<has_table()>. |
c5b9daec |
60 | |
6d84892d |
61 | =head2 Using this Metaclass Trait in Practice |
c5b9daec |
62 | |
6d84892d |
63 | Accessing this new C<table> attribute is quite simple. Given a class |
64 | named C<MyApp::User>, we could simply write the following: |
5377c260 |
65 | |
6d84892d |
66 | my $table = MyApp::User->meta->table; |
67 | |
68 | As long as C<MyApp::User> has arranged to apply the |
69 | C<MyApp::Meta::Class::Trait::HasTable> to its metaclass, this method call just |
70 | works. If we want to be more careful, we can check that the class metaclass |
71 | object has a C<table> method: |
5377c260 |
72 | |
73 | $table = MyApp::User->meta->table |
74 | if MyApp::User->meta->can('table'); |
75 | |
6d84892d |
76 | In theory, this is not entirely correct, since the metaclass might be getting |
77 | its C<table> method from a I<different> trait. In practice, you are unlikely |
78 | to encounter this sort of problem. |
5377c260 |
79 | |
1910e831 |
80 | =head1 RECIPE CAVEAT |
81 | |
82 | This recipe doesn't work when you paste it all into a single file. This is |
83 | because the C<< use Moose -traits => 'HasTable'; >> line ends up being |
84 | executed before the C<table> attribute is defined. |
85 | |
86 | When the two packages are separate files, this just works. |
87 | |
c5b9daec |
88 | =head1 SEE ALSO |
89 | |
b1301316 |
90 | L<Moose::Cookbook::Meta::Labeled_AttributeTrait> - Labels implemented via |
91 | attribute traits |
c5b9daec |
92 | |
c5b9daec |
93 | =pod |
1910e831 |
94 | |
95 | =begin testing |
96 | |
97 | can_ok( MyApp::User->meta, 'table' ); |
98 | is( MyApp::User->meta->table, 'User', 'My::User table is User' ); |
99 | |
100 | =end testing |