Allow CDBI objects to be accessed like hashes as people tend to do for
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / CDBICompat / ColumnsAsHash.pm
CommitLineData
5ef62e9f 1package
2 DBIx::Class::CDBICompat::ColumnsAsHash;
3
4use strict;
5use warnings;
6
7use Scalar::Defer;
8use Scalar::Util qw(weaken);
9use Carp;
10
11
12=head1 NAME
13
14DBIx::Class::CDBICompat::ColumnsAsHash
15
16=head1 SYNOPSIS
17
18See DBIx::Class::CDBICompat for directions for use.
19
20=head1 DESCRIPTION
21
22Emulates the I<undocumnted> behavior of Class::DBI where the object can be accessed as a hash of columns. This is often used as a performance hack.
23
24 my $column = $row->{column};
25
26=head2 Differences from Class::DBI
27
28This will warn when a column is accessed as a hash key.
29
30=cut
31
32sub new {
33 my $class = shift;
34
35 my $new = $class->next::method(@_);
36
37 $new->_make_columns_as_hash;
38
39 return $new;
40}
41
42sub inflate_result {
43 my $class = shift;
44
45 my $new = $class->next::method(@_);
46
47 $new->_make_columns_as_hash;
48
49 return $new;
50}
51
52
53sub _make_columns_as_hash {
54 my $self = shift;
55
56 weaken $self;
57 for my $col ($self->columns) {
58 if( exists $self->{$col} ) {
59 warn "Skipping mapping $col to a hash key because it exists";
60 }
61
62 next unless $self->can($col);
63 $self->{$col} = defer {
64 my $class = ref $self;
65 carp "Column '$col' of '$class/$self' was accessed as a hash";
66 $self->$col();
67 };
68 }
69}
70
71sub update {
72 my $self = shift;
73
74 for my $col ($self->columns) {
75 if( $self->_hash_changed($col) ) {
76 my $class = ref $self;
77 carp "Column '$col' of '$class/$self' was updated as a hash";
78 $self->$col($self->_get_column_from_hash($col));
79 $self->{$col} = defer { $self->$col() };
80 }
81 }
82
83 return $self->next::method(@_);
84}
85
86sub _hash_changed {
87 my($self, $col) = @_;
88
89 return 0 unless exists $self->{$col};
90
91 my $hash = $self->_get_column_from_hash($col);
92 my $obj = $self->$col();
93
94 return 1 if defined $hash xor defined $obj;
95 return 0 if !defined $hash and !defined $obj;
96 return 1 if $hash ne $obj;
97 return 0;
98}
99
100# get the column value without a warning
101sub _get_column_from_hash {
102 my($self, $col) = @_;
103
104 local $SIG{__WARN__} = sub {};
105 return force $self->{$col};
106}
107
1081;