use strict;
use warnings;
-use Scalar::Util qw/blessed/;
use base qw/DBIx::Class::Row/;
=head1 SYNOPSIS
- # In your table classes
- __PACKAGE__->inflate_column('column_name', {
- inflate => sub { ... },
- deflate => sub { ... },
- });
+ # In your table classes
+ __PACKAGE__->inflate_column('column_name', {
+ inflate => sub {
+ my ($raw_value_from_db, $result_object) = @_;
+ ...
+ },
+ deflate => sub {
+ my ($inflated_value_from_user, $result_object) = @_;
+ ...
+ },
+ });
=head1 DESCRIPTION
for the database.
It can be used, for example, to automatically convert to and from
-L<DateTime> objects for your date and time fields.
+L<DateTime> objects for your date and time fields. There's a
+convenience component to actually do that though, try
+L<DBIx::Class::InflateColumn::DateTime>.
+
+It will handle all types of references except scalar references. It
+will not handle scalar values, these are ignored and thus passed
+through to L<SQL::Abstract>. This is to allow setting raw values to
+"just work". Scalar references are passed through to the database to
+deal with, to allow such settings as C< \'year + 1'> and C< \'DEFAULT' >
+to work.
-It will accept arrayrefs, hashrefs and blessed references (objects),
-but not scalarrefs. Scalar references are passed through to the
-database to deal with, to allow such settings as C< \'year + 1'> and
-C< \'DEFAULT' > to work.
+If you want to filter plain scalar values and replace them with
+something else, see L<DBIx::Class::FilterColumn>.
=head1 METHODS
corresponding table class using something like:
__PACKAGE__->inflate_column('insert_time', {
- inflate => sub { DateTime::Format::Pg->parse_datetime(shift); },
- deflate => sub { DateTime::Format::Pg->format_datetime(shift); },
+ inflate => sub {
+ my ($insert_time_raw_value, $event_result_object) = @_;
+ DateTime->from_epoch( epoch => $insert_time_raw_value );
+ },
+ deflate => sub {
+ my ($insert_time_dt_object, $event_result_object) = @_;
+ $insert_time_dt_object->epoch;
+ },
});
-(Replace L<DateTime::Format::Pg> with the appropriate module for your
-database, or consider L<DateTime::Format::DBI>.)
-
The coderefs you set for inflate and deflate are called with two parameters,
-the first is the value of the column to be inflated/deflated, the second is the
-row object itself. Thus you can call C<< ->result_source->schema->storage->dbh >> on
-it, to feed to L<DateTime::Format::DBI>.
+the first is the value of the column to be inflated/deflated, the second is
+the result object itself.
In this example, calls to an event's C<insert_time> accessor return a
-L<DateTime> object. This L<DateTime> object is later "deflated" when
-used in the database layer.
+L<DateTime> object. This L<DateTime> object is later "deflated" back
+to the integer epoch representation when used in the database layer.
+For a much more thorough handling of the above example, please see
+L<DBIx::Class::DateTime::Epoch>
=cut
sub inflate_column {
my ($self, $col, $attrs) = @_;
+
+ my $colinfo = $self->column_info($col);
+
+ $self->throw_exception("InflateColumn does not work with FilterColumn")
+ if $self->isa('DBIx::Class::FilterColumn') &&
+ defined $colinfo->{_filter_info};
+
$self->throw_exception("No such column $col to inflate")
unless $self->has_column($col);
$self->throw_exception("inflate_column needs attr hashref")
unless ref $attrs eq 'HASH';
- $self->column_info($col)->{_inflate_info} = $attrs;
- $self->mk_group_accessors('inflated_column' => [$self->column_info($col)->{accessor} || $col, $col]);
+ $colinfo->{_inflate_info} = $attrs;
+ my $acc = $colinfo->{accessor};
+ $self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]);
return 1;
}
Fetch a column value in its inflated state. This is directly
analogous to L<DBIx::Class::Row/get_column> in that it only fetches a
-column already retreived from the database, and then inflates it.
+column already retrieved from the database, and then inflates it.
Throws an exception if the column requested is not an inflated column.
=cut
unless exists $self->column_info($col)->{_inflate_info};
return $self->{_inflated_column}{$col}
if exists $self->{_inflated_column}{$col};
- return $self->{_inflated_column}{$col} =
- $self->_inflated_column($col, $self->get_column($col));
+
+ my $val = $self->get_column($col);
+ return $val if ref $val eq 'SCALAR'; #that would be a not-yet-reloaded sclarref update
+
+ return $self->{_inflated_column}{$col} = $self->_inflated_column($col, $val);
}
=head2 set_inflated_column
$self->set_column($col, $self->_deflated_column($col, $inflated));
# if (blessed $inflated) {
if (ref $inflated && ref($inflated) ne 'SCALAR') {
- $self->{_inflated_column}{$col} = $inflated;
+ $self->{_inflated_column}{$col} = $inflated;
} else {
- delete $self->{_inflated_column}{$col};
+ delete $self->{_inflated_column}{$col};
}
return $inflated;
}
=over 4
=item L<DBIx::Class::Core> - This component is loaded as part of the
- "core" L<DBIx::Class> components; generally there is no need to
+ C<core> L<DBIx::Class> components; generally there is no need to
load it directly
=back