Commit | Line | Data |
731e8b3e |
1 | package DBIx::Class::Schema::ResultSetAccessors; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
3469a10b |
6 | use base 'DBIx::Class::AccessorGroup'; |
7 | |
77c7c7a8 |
8 | use DBIx::Class::Carp qw(carp); |
731e8b3e |
9 | use String::CamelCase; |
10 | use Lingua::EN::Inflect::Phrase; |
11 | use Sub::Name 'subname'; |
be7d3f83 |
12 | use namespace::clean; |
731e8b3e |
13 | |
3469a10b |
14 | our $VERSION = 0.001005; |
15 | |
16 | __PACKAGE__->mk_group_accessors(inherited => qw/ |
17 | resultset_accessor_map |
18 | _track_resultset_accessors |
19 | /); |
20 | __PACKAGE__->resultset_accessor_map({}); |
21 | __PACKAGE__->_track_resultset_accessors({}); |
6a11ca65 |
22 | |
731e8b3e |
23 | sub register_source { |
6e3c6029 |
24 | my $self = shift; |
731e8b3e |
25 | my $moniker = $_[0]; |
6e3c6029 |
26 | my $next = $self->next::method(@_); |
27 | my $schema = ref($self) || $self; |
28 | |
3469a10b |
29 | # need to track if we already ran register_source once, because |
30 | # it might be re-run in sub-class, like in the case of |
31 | # Catalyst::Model::DBIC::Schema via compose_namespaces |
32 | return $next if |
33 | exists $self->_track_resultset_accessors->{$schema}{$moniker}; |
34 | |
6e3c6029 |
35 | my $accessor_name = |
36 | exists $self->resultset_accessor_map->{$moniker} |
37 | ? $self->resultset_accessor_map->{$moniker} |
38 | : $self->resultset_accessor_name($moniker); |
731e8b3e |
39 | |
731e8b3e |
40 | if ($schema->can($accessor_name)) { |
77c7c7a8 |
41 | carp( |
731e8b3e |
42 | "Can't create ResultSet accessor '$accessor_name'. " . |
43 | "Schema method with the same name already exists. " . |
6e3c6029 |
44 | "Try overloading the name via resultset_accessor_map." |
731e8b3e |
45 | ); |
46 | } |
47 | |
48 | { |
49 | no strict 'refs'; |
50 | no warnings 'redefine'; |
51 | *{"${schema}::${accessor_name}"} = subname "${schema}::${accessor_name}" |
52 | => sub { shift->resultset($moniker) }; |
53 | } |
731e8b3e |
54 | |
3469a10b |
55 | $self->_track_resultset_accessors->{$schema}{$moniker} = 1; |
56 | |
57 | return $next; |
731e8b3e |
58 | } |
59 | |
60 | sub resultset_accessor_name { |
61 | my ($self, $moniker) = @_; |
62 | |
63 | return $self->pluralize_resultset_accessor_name( |
64 | String::CamelCase::decamelize($moniker) |
65 | ); |
66 | } |
67 | |
68 | sub pluralize_resultset_accessor_name { |
6e3c6029 |
69 | my ($self, $original) = @_; |
731e8b3e |
70 | |
867277b3 |
71 | return join '_', split /\s+/, |
6e3c6029 |
72 | Lingua::EN::Inflect::Phrase::to_PL(join ' ', split /_/, $original); |
731e8b3e |
73 | } |
74 | |
75 | 1; # eof |
76 | |
77 | __END__ |
78 | |
79 | =head1 NAME |
80 | |
81 | DBIx::Class::Schema::ResultSetAccessors - Short hand ResultSet Accessors |
82 | |
83 | =head1 SYNOPSIS |
84 | |
3469a10b |
85 | # in your schema class |
86 | __PACKAGE__->load_components(qw/ |
87 | Schema::ResultSetAccessors |
88 | /); |
89 | __PACKAGE__->load_namespaces; |
90 | |
91 | # in your program |
731e8b3e |
92 | use MyApp::Schema; |
93 | my $schema = MyApp::Schema->connect(...); |
731e8b3e |
94 | @artists = $schema->artists->all; # same as $schema->resultset('Artist')->all; |
95 | |
96 | =head1 DESCRIPTION |
97 | |
3469a10b |
98 | Creates short hand accessor methods for each ResultSet. Accessor names are |
731e8b3e |
99 | properly converted into lowercase and pluralized. E.g. |
100 | |
101 | LinerNote -> liner_notes |
102 | Artist -> artists |
103 | CD -> cds |
104 | |
105 | =head1 METHODS |
106 | |
107 | =head2 resultset_accessor_map |
108 | |
109 | Sometimes you will not want to, or will not be able to use an auto-generated |
110 | accessor name. A common case would be when the accessor name conflicts with a |
111 | built in DBIx::Class::Schema method. E.g. if you name your Result class |
112 | "Source", a pluralized version of this would be "sources", which is a built in |
113 | method. |
114 | |
115 | This method allows you to redefine the names as you wish. Overload this method |
116 | in your schema class and return a hashref map of Source => accessor names. E.g.: |
117 | |
118 | # in your MyApp::Schema class |
119 | sub resultset_accessor_map { |
120 | { |
9d76ec7c |
121 | Source => 'my_sources', |
731e8b3e |
122 | Artist => 'my_artists', |
123 | } |
124 | } |
3469a10b |
125 | |
731e8b3e |
126 | # later in your code |
3469a10b |
127 | $schema->my_sources->all; |
731e8b3e |
128 | |
129 | =head2 resultset_accessor_name($moniker) |
130 | |
131 | This method is used to generate the accessor names. If you wish to create your |
132 | own logic for generating the name, you can overload this method. The method |
133 | takes a moniker (aka Source name) as a parameter and returns the accessor name. |
134 | |
135 | Internally it simply uses L<String::CamelCase> to decamelize the name and pass |
136 | it to L</pluralize_resultset_accessor_name> method. |
137 | |
138 | =head2 pluralize_resultset_accessor_name($decamelized_name) |
139 | |
140 | If you only wish to overload the pluralization of the accessor name, in case you |
141 | want to add support for a language other than English, then you might only want |
142 | to overload this method. The method accepts decamelized name (e.g. liner_note) |
143 | and returns properly pluralized version of it. |
144 | |
145 | =head1 SEE ALSO |
146 | |
147 | =over 4 |
148 | |
149 | =item L<DBIx::Class> |
150 | |
151 | =item L<String::CamelCase> |
152 | |
153 | =item L<Lingua::EN::Inflect::Phrase> |
154 | |
155 | =back |
156 | |
157 | =head1 AUTHOR |
158 | |
159 | Roman F. |
160 | romanf@cpan.org |
161 | |
162 | =head1 COPYRIGHT |
163 | |
164 | Copyright (c) 2011 Roman F. |
165 | |
166 | This program is free software; you can redistribute |
167 | it and/or modify it under the same terms as Perl itself. |
168 | |
169 | The full text of the license can be found in the |
170 | LICENSE file included with this module. |
171 | |
172 | =cut |