File: ResultSetManager.pm

package info (click to toggle)
libdbix-class-perl 0.07003-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 1,396 kB
  • ctags: 764
  • sloc: perl: 7,046; sql: 217; makefile: 43
file content (131 lines) | stat: -rw-r--r-- 3,659 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package DBIx::Class::ResultSetManager;
use strict;
use warnings;
use base 'DBIx::Class';
use Class::Inspector;

=head1 NAME

DBIx::Class::ResultSetManager - helpful methods for managing resultset
classes (EXPERIMENTAL)

=head1 SYNOPSIS

  # in a table class
  __PACKAGE__->load_components(qw/ResultSetManager Core/); # note order!

  # will be removed from the table class and inserted into a
  # table-specific resultset class
  sub search_by_year_desc : ResultSet {
    my $self = shift;
    my $cond = shift;
    my $attrs = shift || {};
    $attrs->{order_by} = 'year DESC';
    $self->search($cond, $attrs);
  }

  $rs = $schema->resultset('CD')->search_by_year_desc({ artist => 'Tool' });

=head1 DESCRIPTION

This package implements two useful features for customizing resultset
classes.  C<load_resultset_components> loads components in addition to
C<DBIx::Class::ResultSet> (or whatever you set as
C<base_resultset_class>). Any methods tagged with the C<ResultSet>
attribute will be moved into a table-specific resultset class (by
default called C<Class::_resultset>, but configurable via
C<table_resultset_class_suffix>).  Most of the magic is done when you
call C<< __PACKAGE__->table >>.

=cut

__PACKAGE__->mk_classdata($_)
  for qw/ base_resultset_class table_resultset_class_suffix /;
__PACKAGE__->base_resultset_class('DBIx::Class::ResultSet');
__PACKAGE__->table_resultset_class_suffix('::_resultset');

=head2 table

Stacks on top of the normal L<DBIx::Class> C<table> method.  Any
methods tagged with the C<ResultSet> attribute will be moved into a
table-specific resultset class (by default called
C<Class::_resultset>, but configurable via
C<table_resultset_class_suffix>).  The magic for this is done within
this C<< __PACKAGE__->table >> call.

=cut

sub table {
    my ($self,@rest) = @_;
    my $ret = $self->next::method(@rest);
    if (@rest) {
        $self->_register_attributes;
        $self->_register_resultset_class;
    }
    return $ret;
}

=head2 load_resultset_components

C<load_resultset_components> loads components in addition to
C<DBIx::Class::ResultSet> (or whatever you set as
C<base_resultset_class>).

=cut

sub load_resultset_components {
    my ($self,@comp) = @_;
    my $resultset_class = $self->_setup_resultset_class;
    $resultset_class->load_components(@comp);
}

sub _register_attributes {
    my $self = shift;
    my $cache = $self->_attr_cache;
    return if keys %$cache == 0;

    foreach my $meth (@{Class::Inspector->methods($self) || []}) {
        my $attrs = $cache->{$self->can($meth)};
        next unless $attrs;
        if ($attrs->[0] eq 'ResultSet') {
            no strict 'refs';
            my $resultset_class = $self->_setup_resultset_class;
            *{"$resultset_class\::$meth"} = $self->can($meth);
            delete ${"${self}::"}{$meth};
        }
    }
}

sub _setup_resultset_class {
    my $self = shift;
    my $resultset_class = $self . $self->table_resultset_class_suffix;
    no strict 'refs';
    unless (@{"$resultset_class\::ISA"}) {
        @{"$resultset_class\::ISA"} = ($self->base_resultset_class);
    }
    return $resultset_class;
}

sub _register_resultset_class {
    my $self = shift;
    my $resultset_class = $self . $self->table_resultset_class_suffix;
    no strict 'refs';
    if (@{"$resultset_class\::ISA"}) {
        $self->result_source_instance->resultset_class($resultset_class);
    } else {
        $self->result_source_instance->resultset_class
          ($self->base_resultset_class);
    }
}

1;

=head1 AUTHORS

David Kamholz <dkamholz@cpan.org>

=head1 LICENSE

You may distribute this code under the same terms as Perl itself.

=cut