* Francesc Rom? i Frigol? <[email protected]> [090417 11:39]:
> Marc is more comfortable with a solution that instead of modifying the
> source object, it creates a new row object like this:
> 
> my $copy = bless { %$self, _column_data => $col_data, _inflated_column =>
> $inflated_col }, ref $self;
> $copy = $copy->next::method($changes);
> 
> But either way, the implementation assumes some knowledge of the
> implementation of the base object.
> 
> sub copy {
>     my ($self, $changes) = @_;
> 
>     $changes ||= {};
>     my $col_data     = $self->{_column_data};
>     my $inflated_col = $self->{_inflated_column} ;
> 
>     foreach my $col ( keys %$col_data ) {
>         my $column_info = $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 = $column_info->{accessor} || $col;
>             $changes->{$col} = $self->$accessor;
> 
>             $col_data->{$col} = undef;
>         }
>     }
> 
>     my $copy = $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=5889

Francesc and I have been batting this back and forth off list.  My
current, un-committed implemention for ::FS::copy is:

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

        $changes ||= {};
        my $col_data     = { %{$self->{_column_data}} };

        foreach my $col ( keys %$col_data ) {
            my $column_info = $self->result_source->column_info($col);
            if ( $column_info->{is_fs_column}
                 && defined $col_data->{$col} ) {  # nothing special required 
for NULLs
                $col_data->{$col} = undef;
                
                # pass the original file to produce a copy on deflate
                my $accessor = $column_info->{accessor} || $col;
                $changes->{$col} ||= $self->$accessor;
            }
        }

        my $temp = bless { _column_data => $col_data }, ref $self;
        $temp->result_source($self->result_source);

        my $copy = $temp->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;
    }

When ::FS deflates a column, it makes a copy of the source file in its
own storage path (fs_column_path) UNLESS the inflated value and the
current deflated value (in _column_data) arleady represent the same
file.

So, I create the shallowest copy I can, in ::FS::copy to represent the
source row with the appropriate _column_data set to undef to force a
copy on deflate.  Then I let ::Row::copy do the rest.

After the copy, I delete the inflated fs_columns from _inflated_column
to force inflation from the new copies.

So, DBIC:IC::FS::copy duplicates some of the DBIC:Row internals.  The
question is: Is there a better way?

        -Marc

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/[email protected]

Reply via email to