Cleanup of stale constructor codepath comments
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / InflateColumn.pm
CommitLineData
0e5c2582 1package DBIx::Class::InflateColumn;
2
3use strict;
4use warnings;
aa562407 5
75a23b3e 6use base qw/DBIx::Class::Row/;
0e5c2582 7
75d07914 8=head1 NAME
bcae85db 9
e81a6241 10DBIx::Class::InflateColumn - Automatically create references from column data
bcae85db 11
12=head1 SYNOPSIS
13
14 # In your table classes
15 __PACKAGE__->inflate_column('column_name', {
16 inflate => sub { ... },
17 deflate => sub { ... },
18 });
19
20=head1 DESCRIPTION
21
e81a6241 22This component translates column data into references, i.e. "inflating"
23the column data. It also "deflates" references into an appropriate format
bcae85db 24for the database.
25
26It can be used, for example, to automatically convert to and from
ef7a8b67 27L<DateTime> objects for your date and time fields. There's a
48580715 28convenience component to actually do that though, try
ef7a8b67 29L<DBIx::Class::InflateColumn::DateTime>.
bcae85db 30
ef7a8b67 31It will handle all types of references except scalar references. It
32will not handle scalar values, these are ignored and thus passed
33through to L<SQL::Abstract>. This is to allow setting raw values to
34"just work". Scalar references are passed through to the database to
35deal with, to allow such settings as C< \'year + 1'> and C< \'DEFAULT' >
36to work.
37
38If you want to filter plain scalar values and replace them with
9b2c0de6 39something else, see L<DBIx::Class::FilterColumn>.
e81a6241 40
bcae85db 41=head1 METHODS
42
43=head2 inflate_column
44
75d07914 45Instruct L<DBIx::Class> to inflate the given column.
bcae85db 46
47In addition to the column name, you must provide C<inflate> and
48C<deflate> methods. The C<inflate> method is called when you access
49the field, while the C<deflate> method is called when the field needs
50to used by the database.
51
52For example, if you have a table C<events> with a timestamp field
53named C<insert_time>, you could inflate the column in the
54corresponding table class using something like:
55
56 __PACKAGE__->inflate_column('insert_time', {
57 inflate => sub { DateTime::Format::Pg->parse_datetime(shift); },
58 deflate => sub { DateTime::Format::Pg->format_datetime(shift); },
59 });
60
61(Replace L<DateTime::Format::Pg> with the appropriate module for your
62database, or consider L<DateTime::Format::DBI>.)
63
06fc5fc9 64The coderefs you set for inflate and deflate are called with two parameters,
65the first is the value of the column to be inflated/deflated, the second is the
ef7a8b67 66row object itself. Thus you can call C<< ->result_source->schema->storage->dbh >> in your inflate/defalte subs, to feed to L<DateTime::Format::DBI>.
06fc5fc9 67
bcae85db 68In this example, calls to an event's C<insert_time> accessor return a
69L<DateTime> object. This L<DateTime> object is later "deflated" when
70used in the database layer.
71
72=cut
73
0e5c2582 74sub inflate_column {
75 my ($self, $col, $attrs) = @_;
c227b295 76
52416317 77 my $colinfo = $self->column_info($col);
78
c227b295 79 $self->throw_exception("InflateColumn does not work with FilterColumn")
80 if $self->isa('DBIx::Class::FilterColumn') &&
52416317 81 defined $colinfo->{_filter_info};
c227b295 82
bc0c9800 83 $self->throw_exception("No such column $col to inflate")
84 unless $self->has_column($col);
85 $self->throw_exception("inflate_column needs attr hashref")
86 unless ref $attrs eq 'HASH';
52416317 87 $colinfo->{_inflate_info} = $attrs;
88 my $acc = $colinfo->{accessor};
b82c8a28 89 $self->mk_group_accessors('inflated_column' => [ (defined $acc ? $acc : $col), $col]);
0e5c2582 90 return 1;
91}
92
4a07648a 93sub _inflated_column {
0e5c2582 94 my ($self, $col, $value) = @_;
9f300b1b 95 return $value unless defined $value; # NULL is NULL is NULL
bc0c9800 96 my $info = $self->column_info($col)
97 or $self->throw_exception("No column info for $col");
103647d5 98 return $value unless exists $info->{_inflate_info};
99 my $inflate = $info->{_inflate_info}{inflate};
701da8c4 100 $self->throw_exception("No inflator for $col") unless defined $inflate;
0e5c2582 101 return $inflate->($value, $self);
102}
103
89279e9d 104sub _deflated_column {
105 my ($self, $col, $value) = @_;
e81a6241 106# return $value unless ref $value && blessed($value); # If it's not an object, don't touch it
107 ## Leave scalar refs (ala SQL::Abstract literal SQL), untouched, deflate all other refs
108 return $value unless (ref $value && ref($value) ne 'SCALAR');
89279e9d 109 my $info = $self->column_info($col) or
110 $self->throw_exception("No column info for $col");
111 return $value unless exists $info->{_inflate_info};
112 my $deflate = $info->{_inflate_info}{deflate};
113 $self->throw_exception("No deflator for $col") unless defined $deflate;
114 return $deflate->($value, $self);
0e5c2582 115}
116
7eb4ecc8 117=head2 get_inflated_column
118
119 my $val = $obj->get_inflated_column($col);
120
121Fetch a column value in its inflated state. This is directly
122analogous to L<DBIx::Class::Row/get_column> in that it only fetches a
48580715 123column already retrieved from the database, and then inflates it.
7eb4ecc8 124Throws an exception if the column requested is not an inflated column.
125
126=cut
127
0e5c2582 128sub get_inflated_column {
129 my ($self, $col) = @_;
bc0c9800 130 $self->throw_exception("$col is not an inflated column")
131 unless exists $self->column_info($col)->{_inflate_info};
0e5c2582 132 return $self->{_inflated_column}{$col}
133 if exists $self->{_inflated_column}{$col};
f92b166e 134
135 my $val = $self->get_column($col);
136 return $val if ref $val eq 'SCALAR'; #that would be a not-yet-reloaded sclarref update
137
138 return $self->{_inflated_column}{$col} = $self->_inflated_column($col, $val);
0e5c2582 139}
140
7eb4ecc8 141=head2 set_inflated_column
142
143 my $copy = $obj->set_inflated_column($col => $val);
144
145Sets a column value from an inflated value. This is directly
146analogous to L<DBIx::Class::Row/set_column>.
147
148=cut
149
0e5c2582 150sub set_inflated_column {
ad5d0ee9 151 my ($self, $col, $inflated) = @_;
152 $self->set_column($col, $self->_deflated_column($col, $inflated));
153# if (blessed $inflated) {
154 if (ref $inflated && ref($inflated) ne 'SCALAR') {
9b2c0de6 155 $self->{_inflated_column}{$col} = $inflated;
9f471067 156 } else {
9b2c0de6 157 delete $self->{_inflated_column}{$col};
9f471067 158 }
ad5d0ee9 159 return $inflated;
0e5c2582 160}
161
7eb4ecc8 162=head2 store_inflated_column
163
164 my $copy = $obj->store_inflated_column($col => $val);
165
166Sets a column value from an inflated value without marking the column
47c56124 167as dirty. This is directly analogous to L<DBIx::Class::Row/store_column>.
7eb4ecc8 168
169=cut
170
0e5c2582 171sub store_inflated_column {
ad5d0ee9 172 my ($self, $col, $inflated) = @_;
173# unless (blessed $inflated) {
174 unless (ref $inflated && ref($inflated) ne 'SCALAR') {
9f471067 175 delete $self->{_inflated_column}{$col};
ad5d0ee9 176 $self->store_column($col => $inflated);
177 return $inflated;
9f471067 178 }
25594f03 179 delete $self->{_column_data}{$col};
ad5d0ee9 180 return $self->{_inflated_column}{$col} = $inflated;
180c7679 181}
4a07648a 182
bcae85db 183=head1 SEE ALSO
184
185=over 4
186
187=item L<DBIx::Class::Core> - This component is loaded as part of the
d88ecca6 188 C<core> L<DBIx::Class> components; generally there is no need to
bcae85db 189 load it directly
190
191=back
192
193=head1 AUTHOR
194
195Matt S. Trout <mst@shadowcatsystems.co.uk>
196
197=head1 CONTRIBUTORS
198
199Daniel Westermann-Clark <danieltwc@cpan.org> (documentation)
200
e81a6241 201Jess Robinson <cpan@desert-island.demon.co.uk>
202
bcae85db 203=head1 LICENSE
204
205You may distribute this code under the same terms as Perl itself.
206
207=cut
208
0e5c2582 2091;