1 package DBIx::Class::ResultClass::HashRefInflator;
8 DBIx::Class::ResultClass::HashRefInflator
12 use DBIx::Class::ResultClass::HashRefInflator;
14 my $rs = $schema->resultset('CD');
16 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
18 $rs->result_class(DBIx::Class::ResultClass::HashRefInflator->new (%args));
20 while (my $hashref = $rs->next) {
26 DBIx::Class is faster than older ORMs like Class::DBI but it still isn't
27 designed primarily for speed. Sometimes you need to quickly retrieve the data
28 from a massive resultset, while skipping the creation of fancy row objects.
29 Specifying this class as a C<result_class> for a resultset will change C<< $rs->next >>
30 to return a plain data hash-ref (or a list of such hash-refs if C<< $rs->all >> is used).
32 There are two ways of using this class:
38 Supply an instance of DBIx::Class::ResultClass::HashRefInflator to
39 C<< $rs->result_class >>. See L</ARGUMENTS> for a list of valid
44 Another way is to simply supply the class name as a string to
45 C<< $rs->result_class >>. Equivalent to passing
46 DBIx::Class::ResultClass::HashRefInflator->new().
50 There are two ways of applying this class to a resultset:
56 Specify C<< $rs->result_class >> on a specific resultset to affect only that
57 resultset (and any chained off of it); or
61 Specify C<< __PACKAGE__->result_class >> on your source object to force all
62 uses of that result source to be inflated to hash-refs - this approach is not
72 # Generally people use this to gain as much speed as possible. If a new &mk_hash is
73 # implemented, it should be benchmarked using the maint/benchmark_hashrefinflator.pl
74 # script (in addition to passing all tests of course :). Additional instructions are
75 # provided in the script itself.
78 # This coderef is a simple recursive function
79 # Arguments: ($me, $prefetch) from inflate_result() below
82 if (ref $_[0] eq 'ARRAY') { # multi relationship
83 return [ map { $mk_hash->(@$_) || () } (@_) ];
87 # the main hash could be an undef if we are processing a skipped-over join
88 $_[0] ? %{$_[0]} : (),
90 # the second arg is a hash of arrays for each prefetched relation
92 { $_ => $mk_hash->( @{$_[1]->{$_}} ) }
93 ( $_[1] ? (keys %{$_[1]}) : () )
96 # if there is at least one defined column consider the resultset real
97 # (and not an emtpy has_many rel containing one empty hashref)
99 return $hash if defined $_;
106 # This is the inflator
108 $inflate_hash = sub {
109 my ($hri_instance, $schema, $rc, $data) = @_;
111 foreach my $column (keys %{$data}) {
113 if (ref $data->{$column} eq 'HASH') {
114 $inflate_hash->($hri_instance, $schema, $schema->source ($rc)->related_class ($column), $data->{$column});
116 elsif (ref $data->{$column} eq 'ARRAY') {
117 foreach my $rel (@{$data->{$column}}) {
118 $inflate_hash->($hri_instance, $schema, $schema->source ($rc)->related_class ($column), $rel);
122 # "null is null is null"
123 next if not defined $data->{$column};
125 # cache the inflator coderef
126 unless (exists $hri_instance->{_inflator_cache}{$rc}{$column}) {
127 $hri_instance->{_inflator_cache}{$rc}{$column} = exists $schema->source ($rc)->_relationships->{$column}
128 ? undef # currently no way to inflate a column sharing a name with a rel
129 : $rc->column_info($column)->{_inflate_info}{inflate}
133 if ($hri_instance->{_inflator_cache}{$rc}{$column}) {
134 $data->{$column} = $hri_instance->{_inflator_cache}{$rc}{$column}->($data->{$column});
145 $class->new( %args );
146 $class->new({ %args });
148 Creates a new DBIx::Class::ResultClass::HashRefInflator object. Takes the following
153 =item inflate_columns
155 Sometimes you still want all your data to be inflated to the corresponding
156 objects according to the rules you defined in your table classes (e.g. you
157 want all dates in the resulting hash to be replaced with the equivalent
158 DateTime objects). Supplying C<< inflate_columns => 1 >> to the constructor will
159 interrogate the processed columns and apply any inflation methods declared
160 via L<DBIx::Class::InflateColumn/inflate_column> to the contents of the
169 my $args = { (ref $_[0] eq 'HASH') ? %{$_[0]} : @_ };
170 return bless ($args, $self)
173 =head2 inflate_result
175 Inflates the result and prefetched data into a hash-ref (invoked by L<DBIx::Class::ResultSet>)
181 my ($self, $source, $me, $prefetch) = @_;
183 my $hashref = $mk_hash->($me, $prefetch);
185 # if $self is an instance and inflate_columns is set
186 if ( (ref $self) and $self->{inflate_columns} ) {
187 $inflate_hash->($self, $source->schema, $source->result_class, $hashref);
200 This will not work for relationships that have been prefetched. Consider the
203 my $artist = $artitsts_rs->search({}, {prefetch => 'cds' })->first;
205 my $cds = $artist->cds;
206 $cds->result_class('DBIx::Class::ResultClass::HashRefInflator');
207 my $first = $cds->first;
209 C<$first> will B<not> be a hashref, it will be a normal CD row since
210 HashRefInflator only affects resultsets at inflation time, and prefetch causes
211 relations to be inflated when the master C<$artist> row is inflated.
215 When using C<inflate_columns>, the inflation method lookups are cached in the
216 HashRefInflator object for additional speed. If you modify column inflators at run
217 time, make sure to grab a new instance of this class to avoid cached surprises.