File Coverage

blib/lib/DBIx/Class/Schema/ResultSetNames.pm
Criterion Covered Total %
statement 51 52 98.0
branch 4 6 66.6
condition n/a
subroutine 13 13 100.0
pod 1 1 100.0
total 69 72 95.8


line stmt bran cond sub pod time code
1             package DBIx::Class::Schema::ResultSetNames 1.02;
2 1     1   146984 use strict;
  1         11  
  1         32  
3 1     1   6 use warnings;
  1         2  
  1         32  
4 1     1   6 use base qw(DBIx::Class::Schema);
  1         2  
  1         160  
5 1     1   581 use Lingua::EN::Inflect::Phrase;
  1         105450  
  1         156  
6              
7             __PACKAGE__->mk_group_accessors( inherited => 'resultset_name_methods' );
8              
9             __PACKAGE__->resultset_name_methods( {} );
10              
11             sub register_source {
12 2     2 1 110534 my ( $class, $source_name, @rest ) = @_;
13 2         19 my $source = $class->next::method( $source_name, @rest );
14 2         931 $class->_register_resultset_name_methods($source_name);
15 2         19 return $source;
16             }
17              
18             sub _ensure_resultset_name_method {
19 4     4   16 my ( $class, $name, $sub ) = @_;
20 4 50       99 return if $class->can($name);
21             {
22 1     1   13 no strict 'refs';
  1         2  
  1         528  
  4         12  
23 4         10 *{"${class}::${name}"} = $sub;
  4         21  
24             }
25             $class->resultset_name_methods(
26 4         11 { %{ $class->resultset_name_methods }, $name => 1 }, );
  4         152  
27 4         246 return;
28             }
29              
30             sub _register_resultset_name_methods {
31 2     2   8 my ( $class, $source_name ) = @_;
32 2         11 my $method_name = $class->_source_name_to_method_name($source_name);
33 2         9 my $plural_name = $class->_source_name_to_plural_name($source_name);
34             $class->_ensure_resultset_name_method(
35             $method_name => sub {
36 9     9   89394 my ( $self, @args ) = @_;
37 9 100       81 die "Can't call ${method_name} without arguments" unless @args;
38 7         52 $self->resultset($source_name)->find(@args);
39             }
40 2         80 );
41             $class->_ensure_resultset_name_method(
42             $plural_name => sub {
43 6     6   182176 my ( $self, @args ) = @_;
44 6         58 my $rs = $self->resultset($source_name);
45 6 50       3753 return $rs unless @args;
46 0         0 return $rs->search_rs(@args);
47             }
48 2         22 );
49 2         7 return;
50             }
51              
52             sub _source_name_to_method_name {
53 2     2   7 my ( $class, $source_name ) = @_;
54 2         10 my $phrase = $class->_source_name_to_phrase($source_name);
55 2         9 return join '_', split q{ }, $phrase;
56             }
57              
58             sub _source_name_to_phrase {
59 4     4   10 my ( $class, $source_name ) = @_;
60             join q{ }, map {
61 4         17 join( q{ }, map {lc} grep {length} split /([A-Z]{1}[^A-Z]*)/ )
  4         22  
  4         24  
  8         19  
62             } split /::/, $source_name;
63             }
64              
65             sub _source_name_to_plural_name {
66 2     2   17 my ( $class, $source_name ) = @_;
67 2         9 my $phrase = $class->_source_name_to_phrase($source_name);
68 2         11 my $pluralised = Lingua::EN::Inflect::Phrase::to_PL($phrase);
69 2         200402 return join '_', split q{ }, $pluralised;
70             }
71              
72             1;
73              
74             =pod
75              
76             =encoding UTF-8
77              
78             =head1 NAME
79              
80             DBIx::Class::Schema::ResultSetNames - Create resultset accessors from table names
81              
82             =head1 VERSION
83              
84             version 1.02
85              
86             =head1 SYNOPSIS
87              
88             # in MyApp::Schema
89             __PACKAGE__->load_components('Schema::ResultSetNames');
90              
91             =head1 DESCRIPTION
92              
93             DBIx::Class::Schema::ResultSetNames adds both singular and plural method accessors for all resultsets.
94              
95             So, instead of this:
96              
97             my $schema = MyApp::Schema->connect(...);
98             my $result = $schema->resultset('Author')->search({...});
99              
100             you may choose to this:
101              
102             my $schema = MyApp::Schema->connect(...);
103             my $result = $schema->authors->search({...});
104              
105             And instead of this:
106              
107             my $schema = MyApp::Schema->connect(...);
108             my $result = $schema->resultset('Author')->find($id);
109              
110             you may choose to this:
111              
112             my $schema = MyApp::Schema->connect(...);
113             my $result = $schema->author($id)
114              
115             =head2 What is returned?
116              
117             If you call the plural form of the resultset (e.g. `authors`), you will get a L,
118             which may be empty, if no rows satisfy whatever criteria you've chained behind it.
119              
120             For the singular form (`author`), you'll get a L, or `undef`, if the selected row does not exist.
121              
122             =head2 A note about `find`.
123              
124             It is perfectly permissible to use find (or the singular accessor, in this module) to locate something
125             by including a hashref of search terms:
126              
127             my $result = $schema->resultSet('Author')->find({ name => 'John Smith }); # Old way
128             my $result = $schema->author({ name => 'John Smith' }); # New way
129              
130             However, be aware that `find()` and this module will both complain if your request will return multiple
131             rows, and throw a warning. `find()` expects to return one row or undef, which is why it is best used on unique keys.
132              
133             =head2 "Let not your heart be troubled..." about relationships.
134              
135             This doesn't tamper with relationship accessors in any way. If you have a table of Authors and a table of Books,
136             the usual sort of `book($id)->author()`, and `author($id)->books()` relationship tools will still work just fine.
137              
138             =head1 SEE ALSO
139              
140             =over 4
141              
142             =item * L
143              
144             =item * L
145              
146             =back
147              
148             =head1 CREDIT WHERE CREDIT IS DUE
149              
150             Practically all of this code is the work of L. It was
151             created alongside a Dancer2 plugin that he has helped greatly with. I just tidied things up and wrote
152             documentation.
153              
154             =head1 SOURCE
155              
156             L
157              
158             =head1 HOMEPAGE
159              
160             L
161              
162             =head1 AUTHOR
163              
164             D Ruth Holloway
165              
166             =head1 COPYRIGHT AND LICENSE
167              
168             This software is copyright (c) 2021 by D Ruth Holloway.
169              
170             This is free software; you can redistribute it and/or modify it under
171             the same terms as the Perl 5 programming language system itself.
172              
173             =cut
174              
175             __END__