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