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