Add pod for params of inflate/deflate coderefs
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / InflateColumn.pm
CommitLineData
0e5c2582 1package DBIx::Class::InflateColumn;
2
3use strict;
4use warnings;
aa562407 5
aa562407 6
75a23b3e 7use base qw/DBIx::Class::Row/;
0e5c2582 8
75d07914 9=head1 NAME
bcae85db 10
11DBIx::Class::InflateColumn - Automatically create objects from column data
12
13=head1 SYNOPSIS
14
15 # In your table classes
16 __PACKAGE__->inflate_column('column_name', {
17 inflate => sub { ... },
18 deflate => sub { ... },
19 });
20
21=head1 DESCRIPTION
22
23This component translates column data into objects, i.e. "inflating"
24the column data. It also "deflates" objects into an appropriate format
25for the database.
26
27It can be used, for example, to automatically convert to and from
75d07914 28L<DateTime> objects for your date and time fields.
bcae85db 29
30=head1 METHODS
31
32=head2 inflate_column
33
75d07914 34Instruct L<DBIx::Class> to inflate the given column.
bcae85db 35
36In addition to the column name, you must provide C<inflate> and
37C<deflate> methods. The C<inflate> method is called when you access
38the field, while the C<deflate> method is called when the field needs
39to used by the database.
40
41For example, if you have a table C<events> with a timestamp field
42named C<insert_time>, you could inflate the column in the
43corresponding table class using something like:
44
45 __PACKAGE__->inflate_column('insert_time', {
46 inflate => sub { DateTime::Format::Pg->parse_datetime(shift); },
47 deflate => sub { DateTime::Format::Pg->format_datetime(shift); },
48 });
49
50(Replace L<DateTime::Format::Pg> with the appropriate module for your
51database, or consider L<DateTime::Format::DBI>.)
52
06fc5fc9 53The coderefs you set for inflate and deflate are called with two parameters,
54the first is the value of the column to be inflated/deflated, the second is the
55row object itself. Thus you can call C<< ->result_source->schema->storage->dbh >> on
56it, to feed to L<DateTime::Format::DBI>.
57
bcae85db 58In this example, calls to an event's C<insert_time> accessor return a
59L<DateTime> object. This L<DateTime> object is later "deflated" when
60used in the database layer.
61
62=cut
63
0e5c2582 64sub inflate_column {
65 my ($self, $col, $attrs) = @_;
bc0c9800 66 $self->throw_exception("No such column $col to inflate")
67 unless $self->has_column($col);
68 $self->throw_exception("inflate_column needs attr hashref")
69 unless ref $attrs eq 'HASH';
103647d5 70 $self->column_info($col)->{_inflate_info} = $attrs;
0e5c2582 71 $self->mk_group_accessors('inflated_column' => $col);
72 return 1;
73}
74
4a07648a 75sub _inflated_column {
0e5c2582 76 my ($self, $col, $value) = @_;
9f300b1b 77 return $value unless defined $value; # NULL is NULL is NULL
bc0c9800 78 my $info = $self->column_info($col)
79 or $self->throw_exception("No column info for $col");
103647d5 80 return $value unless exists $info->{_inflate_info};
81 my $inflate = $info->{_inflate_info}{inflate};
701da8c4 82 $self->throw_exception("No inflator for $col") unless defined $inflate;
0e5c2582 83 return $inflate->($value, $self);
84}
85
4a07648a 86sub _deflated_column {
0e5c2582 87 my ($self, $col, $value) = @_;
88 return $value unless ref $value; # If it's not an object, don't touch it
bc0c9800 89 my $info = $self->column_info($col) or
90 $self->throw_exception("No column info for $col");
103647d5 91 return $value unless exists $info->{_inflate_info};
92 my $deflate = $info->{_inflate_info}{deflate};
701da8c4 93 $self->throw_exception("No deflator for $col") unless defined $deflate;
0e5c2582 94 return $deflate->($value, $self);
95}
96
97sub get_inflated_column {
98 my ($self, $col) = @_;
bc0c9800 99 $self->throw_exception("$col is not an inflated column")
100 unless exists $self->column_info($col)->{_inflate_info};
4a07648a 101
0e5c2582 102 return $self->{_inflated_column}{$col}
103 if exists $self->{_inflated_column}{$col};
0e5c2582 104 return $self->{_inflated_column}{$col} =
4a07648a 105 $self->_inflated_column($col, $self->get_column($col));
0e5c2582 106}
107
108sub set_inflated_column {
109 my ($self, $col, @rest) = @_;
47bd0267 110 my $ret = $self->_inflated_column_op('set', $col, @rest);
0e5c2582 111 return $ret;
112}
113
114sub store_inflated_column {
47bd0267 115 my ($self, $col, @rest) = @_;
116 my $ret = $self->_inflated_column_op('store', $col, @rest);
117 return $ret;
118}
119
120sub _inflated_column_op {
121 my ($self, $op, $col, $obj) = @_;
122 my $meth = "${op}_column";
0e5c2582 123 unless (ref $obj) {
124 delete $self->{_inflated_column}{$col};
47bd0267 125 return $self->$meth($col, $obj);
0e5c2582 126 }
4a07648a 127
128 my $deflated = $self->_deflated_column($col, $obj);
9f300b1b 129 # Do this now so we don't store if it's invalid
4a07648a 130
0e5c2582 131 $self->{_inflated_column}{$col} = $obj;
47bd0267 132 $self->$meth($col, $deflated);
0e5c2582 133 return $obj;
134}
135
9fcda149 136sub update {
137 my ($class, $attrs, @rest) = @_;
138 $attrs ||= {};
139 foreach my $key (keys %$attrs) {
140 if (ref $attrs->{$key}
141 && exists $class->column_info($key)->{_inflate_info}) {
e9100ff7 142# $attrs->{$key} = $class->_deflated_column($key, $attrs->{$key});
143 $class->set_inflated_column ($key, delete $attrs->{$key});
9fcda149 144 }
145 }
146 return $class->next::method($attrs, @rest);
147}
148
0e5c2582 149sub new {
150 my ($class, $attrs, @rest) = @_;
151 $attrs ||= {};
0e5c2582 152 foreach my $key (keys %$attrs) {
103647d5 153 if (ref $attrs->{$key}
154 && exists $class->column_info($key)->{_inflate_info}) {
484c9dda 155 $attrs->{$key} = $class->_deflated_column($key, $attrs->{$key});
0e5c2582 156 }
157 }
147dd158 158 return $class->next::method($attrs, @rest);
0e5c2582 159}
160
bcae85db 161=head1 SEE ALSO
162
163=over 4
164
165=item L<DBIx::Class::Core> - This component is loaded as part of the
166 "core" L<DBIx::Class> components; generally there is no need to
167 load it directly
168
169=back
170
171=head1 AUTHOR
172
173Matt S. Trout <mst@shadowcatsystems.co.uk>
174
175=head1 CONTRIBUTORS
176
177Daniel Westermann-Clark <danieltwc@cpan.org> (documentation)
178
179=head1 LICENSE
180
181You may distribute this code under the same terms as Perl itself.
182
183=cut
184
0e5c2582 1851;