--- /dev/null
+package
+ DBIx::Class::CDBICompat::ColumnsAsHash;
+
+use strict;
+use warnings;
+
+use Scalar::Defer;
+use Scalar::Util qw(weaken);
+use Carp;
+
+
+=head1 NAME
+
+DBIx::Class::CDBICompat::ColumnsAsHash
+
+=head1 SYNOPSIS
+
+See DBIx::Class::CDBICompat for directions for use.
+
+=head1 DESCRIPTION
+
+Emulates 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.
+
+ my $column = $row->{column};
+
+=head2 Differences from Class::DBI
+
+This will warn when a column is accessed as a hash key.
+
+=cut
+
+sub new {
+ my $class = shift;
+
+ my $new = $class->next::method(@_);
+
+ $new->_make_columns_as_hash;
+
+ return $new;
+}
+
+sub inflate_result {
+ my $class = shift;
+
+ my $new = $class->next::method(@_);
+
+ $new->_make_columns_as_hash;
+
+ return $new;
+}
+
+
+sub _make_columns_as_hash {
+ my $self = shift;
+
+ weaken $self;
+ for my $col ($self->columns) {
+ if( exists $self->{$col} ) {
+ warn "Skipping mapping $col to a hash key because it exists";
+ }
+
+ next unless $self->can($col);
+ $self->{$col} = defer {
+ my $class = ref $self;
+ carp "Column '$col' of '$class/$self' was accessed as a hash";
+ $self->$col();
+ };
+ }
+}
+
+sub update {
+ my $self = shift;
+
+ for my $col ($self->columns) {
+ if( $self->_hash_changed($col) ) {
+ my $class = ref $self;
+ carp "Column '$col' of '$class/$self' was updated as a hash";
+ $self->$col($self->_get_column_from_hash($col));
+ $self->{$col} = defer { $self->$col() };
+ }
+ }
+
+ return $self->next::method(@_);
+}
+
+sub _hash_changed {
+ my($self, $col) = @_;
+
+ return 0 unless exists $self->{$col};
+
+ my $hash = $self->_get_column_from_hash($col);
+ my $obj = $self->$col();
+
+ return 1 if defined $hash xor defined $obj;
+ return 0 if !defined $hash and !defined $obj;
+ return 1 if $hash ne $obj;
+ return 0;
+}
+
+# get the column value without a warning
+sub _get_column_from_hash {
+ my($self, $col) = @_;
+
+ local $SIG{__WARN__} = sub {};
+ return force $self->{$col};
+}
+
+1;
},
'DBIx::Class::CDBICompat::AttributeAPI' => { skip => 1 },
'DBIx::Class::CDBICompat::AutoUpdate' => { skip => 1 },
+ 'DBIx::Class::CDBICompat::ColumnsAsHash' => {
+ ignore => [qw(inflate_result new update)]
+ },
'DBIx::Class::CDBICompat::ColumnCase' => { skip => 1 },
'DBIx::Class::CDBICompat::ColumnGroups' => { skip => 1 },
'DBIx::Class::CDBICompat::Constraints' => { skip => 1 },
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use Test::More;
+use Test::Warn;
+
+BEGIN {
+ eval "use DBIx::Class::CDBICompat;";
+ plan $@ ? (skip_all => "Class::Trigger and DBIx::ContextualFetch required: $@")
+ : (tests=> 6);
+}
+
+use lib 't/testlib';
+use Film;
+
+my $waves = Film->insert({
+ Title => "Breaking the Waves",
+ Director => 'Lars von Trier',
+ Rating => 'R'
+});
+
+warnings_like {
+ is $waves->{title}, $waves->Title, "columns can be accessed as hashes";
+} qr{^Column 'title' of 'Film/$waves' was accessed as a hash at .*$};
+
+$waves->Rating("G");
+
+warnings_like {
+ is $waves->{rating}, "G", "updating via the accessor updates the hash";
+} qr{^Column 'rating' of 'Film/$waves' was accessed as a hash .*$};
+
+$waves->{rating} = "PG";
+
+warnings_like {
+ $waves->update;
+} qr{^Column 'rating' of 'Film/$waves' was updated as a hash .*$};
+
+my @films = Film->search( Rating => "PG", Title => "Breaking the Waves" );
+is @films, 1, "column updated as hash was saved";