[Dbix-class] InflateColumn with objects external to the database (like InflateColumn::FS)

Francesc Romà i Frigolé francesc.roma+dbix at gmail.com
Fri Apr 17 18:35:12 GMT 2009


Hello list,

If I understand DBIx::Class::InflateColumn properly, it automatically
converts column data into references and the other way around, but it
doesn't take into account the possibility that the stored value could be
some sort of a unique ID ( like a file name, process id, socket...)

Imagine you store a file name in the column which you inflate to a file
object. If you copy one of the rows, you end up with two rows with the same
file name. This is inconsistent since if we delete one of the rows, the
other will have a reference to a file which no longer exists.

There is an InflateColumn::File class in the DBIC distribution, which has
been broken for a while, and Marc Mims has written an improved module called
InflateColumn::FS to replace it. I've been trying to help him with the copy
issue but I can't figure out how to solve the problem without directly
changing the state of the source object, changing the attributes
_inflated_column and _column_data to force reinflation.

Is it possible to solve the problem without accessing/changing private
attributes? Also (specially if the previous answer is no), wouldn't it make
more sense to factor out the logic to keep the inflatable column unique?
This  code could be incorporated into DBIx::Class::InflateColumn, or maybe a
different module like DBIx::Class::InflateColum::Unique

Below is my proposed implementation of FS::copy. Marc is more comfortable
with a solution that instead of modifying the source object, it creates a
new row object like this:

my $copy =3D bless { %$self, _column_data =3D> $col_data, _inflated_column =
=3D>
$inflated_col }, ref $self;
$copy =3D $copy->next::method($changes);

But either way, the implementation assumes some knowledge of the
implementation of the base object.

sub copy {
    my ($self, $changes) =3D @_;

    $changes ||=3D {};
    my $col_data     =3D $self->{_column_data};
    my $inflated_col =3D $self->{_inflated_column} ;

    foreach my $col ( keys %$col_data ) {
        my $column_info =3D $self->result_source->column_info($col);
        if ( $column_info->{is_fs_column}
             && defined $col_data->{$col}  # nothing special required for
NULLs
             && !exists $changes->{$col} ) {

            # pass the original file to produce a copy on deflate
            my $accessor =3D $column_info->{accessor} || $col;
            $changes->{$col} =3D $self->$accessor;

            $col_data->{$col} =3D undef;
        }
    }

    my $copy =3D $self->next::method($changes);

    # force reinflation of fs colmuns on next access
    delete $copy->{_inflated_column}{$_}
        for grep { $self->result_source->column_info($_)->{is_fs_column} }
            keys %$col_data;

   return $copy;
}

links to cpan and repository:
http://search.cpan.org/perldoc?DBIx::Class::InflateColumn::FS
http://dev.catalyst.perl.org/svnweb/bast/revision?rev=3D5889

Thanks for your advise,
Francesc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/dbix-class/attachments/20090417/26f=
ece46/attachment.htm


More information about the DBIx-Class mailing list