945bcfdc58d5425d9dcf1e252b6a08fa1c54e9f2
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultClass / HashRefInflator.pm
1 package DBIx::Class::ResultClass::HashRefInflator;
2
3 use strict;
4 use warnings;
5
6 =head1 NAME
7
8 DBIx::Class::ResultClass::HashRefInflator
9
10 =head1 SYNOPSIS
11
12  my $rs = $schema->resultset('CD');
13
14  $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
15
16 =head1 DESCRIPTION
17
18 DBIx::Class is not built for speed: it's built for convenience and
19 ease of use. But sometimes you just need to get the data, and skip the
20 fancy objects. That is what this class provides.
21
22 There are two ways of using this class.
23
24 =over
25
26 =item *
27
28 Specify C<< $rs->result_class >> on a specific resultset to affect only that
29 resultset (and any chained off of it); or
30
31 =item *
32
33 Specify C<< __PACKAGE__->result_class >> on your source object to force all
34 uses of that result source to be inflated to hash-refs - this approach is not
35 recommended.
36
37 =back
38
39 =head1 AUTOMATICALLY INFLATING COLUMN VALUES
40
41 So you want to skip the DBIx::Class object creation part, but you still want 
42 all your data to be inflated according to the rules you defined in your table
43 classes. Setting the global variable 
44 C<$DBIx::Class::ResultClass::HashRefInflator::inflate_data> to a true value
45 will instruct L<mk_hash> to interrogate the processed columns and apply any
46 inflation methods declared via L<DBIx::Class::InflateColumn/inflate_column>.
47
48 For increased speed the inflation method lookups are cached in 
49 C<%DBIx::Class::ResultClass::HashRefInflator::inflator_cache>. Make sure to 
50 reset this hash if you modify column inflators at run time.
51
52 =head1 METHODS
53
54 =head2 inflate_result
55
56 Inflates the result and prefetched data into a hash-ref using L<mk_hash>.
57
58 =cut
59
60 sub inflate_result {
61     my ($self, $source, $me, $prefetch) = @_;
62
63     my $hashref = mk_hash($me, $prefetch);
64     return $hashref;
65 }
66
67 =head2 mk_hash
68
69 This does all the work of inflating the (pre)fetched data.
70
71 =cut
72
73 ##############
74 # NOTE
75 #
76 # Generally people use this to gain as much speed as possible. If a new mk_hash is
77 # implemented, it should be benchmarked using the maint/benchmark_hashrefinflator.pl
78 # script (in addition to passing all tests of course :). Additional instructions are 
79 # provided in the script itself.
80 #
81
82 sub mk_hash { 
83     if (ref $_[0] eq 'ARRAY') {     # multi relationship
84         return [ map { mk_hash (@$_) || () } (@_) ];
85     }
86     else {
87         my $hash = {
88             # the main hash could be an undef if we are processing a skipped-over join
89             $_[0] ? %{$_[0]} : (),
90
91             # the second arg is a hash of arrays for each prefetched relation
92             map
93                 { $_ => mk_hash( @{$_[1]->{$_}} ) }
94                 ( $_[1] ? (keys %{$_[1]}) : () )
95         };
96
97         # if there is at least one defined column consider the resultset real
98         # (and not an emtpy has_many rel containing one empty hashref)
99         for (values %$hash) {
100             return $hash if defined $_;
101         }
102
103         return undef;
104     }
105 }
106
107 =head1 CAVEAT
108
109 This will not work for relationships that have been prefetched. Consider the
110 following:
111
112  my $artist = $artitsts_rs->search({}, {prefetch => 'cds' })->first;
113
114  my $cds = $artist->cds;
115  $cds->result_class('DBIx::Class::ResultClass::HashRefInflator');
116  my $first = $cds->first; 
117
118 C<$first> will B<not> be a hashref, it will be a normal CD row since 
119 HashRefInflator only affects resultsets at inflation time, and prefetch causes
120 relations to be inflated when the master C<$artist> row is inflated.
121
122 =cut
123
124 1;