Good evening,

On 25/01/10 at 8:08 AM +0200, [email protected] wrote:

From: "Charlie Garrison" <[email protected]>
On 24/01/10 at 10:47 PM +0200, Octavian Rasnita <[email protected]> wrote:

I had some problems with InflateColumn::File a few weeks ago which
were going to be hard for me to work around. I asked about it on IRC
and was told *not* to use the broken InflateColumn::File and use
InflateColumn::FS instead.

Can you tell about those problems? I hope I won't create them in the inflator I 
want to create.

I don't recall exactly, but IC::File had problems with multiple 'file' columns. I remember, the delete part was completely broken if all files were not in the same directory. I was trying to patch IC::File so that deleting would work; I was advised to use IC::FS rather than trying to fix IC::File. (I don't recall who said that, sorry.)

Not only did InflateColumn::FS resolve my main issue; it also fixed a
couple of frustrating niggles. I found InflateColumn::FS to be more
robust all around.

I have also tried InflateColumn::FS but the thing I don't like is that
it creates random directories and this is good from a security point of
view, but for ease of use I like the way InflateColumn::File create the
target dirs.

One of the reasons I found IC::FS so much better, was the extra control for things like how files are named/stored on disk. From the POD:

fs_file_name
Provides the file naming algorithm. Override this method to change it. This method is called with two parameters: The name of the column and the column_info object.

_fs_column_dirs
Returns the sub-directory components for a given file name. Override it to provide a deeper directory tree or change the algorithm.

Eg (example from myApp; I used a different naming scheme in the end, but this shows the flexibility of IC::FS):

sub fs_file_name {
    my ($self, $column, $column_info) = @_;
my MIME::Type $img_mimetype = MIME::Types->new->type($self->mime_type); #'image/jpeg'
    my $size = $column eq 'media_full_file'  ?
                    'full' :
               $column eq 'media_thumb_file' ?
                    'thumb' :
               $column eq 'media_orig_file'  ?
                    'orig' :
                    '';
    return sprintf("%05d-%s_%s.%s",
        $self->user->id,
        $self->name,
        $size,
        $img_mimetype->subType)
}

I ended up using something very close to the original method, I just wanted to add the file extension:

sub fs_file_name {
    my ($self, $column, $column_info) = @_;
my MIME::Type $img_mimetype = MIME::Types->new->type($self->mime_type); #'image/jpeg'
    return sprintf("%s.%s", DBIx::Class::UUIDColumns->get_uuid, 
$img_mimetype->subType)
}

I'm sure it's possible to use the original file name (from upload param), but I didn't want to use that anyway. So again, IC:FS was an easy win for me.

Note, I find the sub-dirs created with IC::FS much more desirable than putting them all in one directory (for scaling reasons). I was looking at ways of patching IC:File to do that since I wasn't looking forward to many thousands of directory entries in my media dir. And if I find that two-letter sub dirs isn't enough (I hope we get that big), I can easily change that by overriding _fs_column_dirs.

With InflateColumn::File the original file name is also used when it is
stored on the disk, and I just need to put a link to that static file,
without needing to create a column for storing the MIME type of the
file and without needing to use code for getting the file and giving it
to those that request it. If it is possible to do that with
InflateColumn::FS, please tell me.

Create a method that returns the file path and call that when you need to create URL pointing to the file:

sub fs_file_path {
    my ($self, $column) = @_;
    my $fh = $self->$column;
return $fh->relative( $self->result_source->column_info($column)->{fs_column_path} )->stringify;
}

And I created some wrapper methods for each column:

sub media_full_file_path { shift->fs_file_path('media_full_file'); } sub media_thumb_file_path { shift->fs_file_path('media_thumb_file'); } sub media_orig_file_path { shift->fs_file_path('media_orig_file'); }

In my template:

[% img_full_src = c.uri_for("/static/media/${user_image.media_full_file_path}" );
    img_thumb_src  = 
c.uri_for("/static/media/${user_image.media_thumb_file_path}");
-%]

Note, fs_file_path return a two-part path, so the value needs to be passed as part of first arg to uri_for. Otherwise, if passed as second arg, the slash will get encoded and things may not work as expected.


If you're going to upload an HTML::FF inflator module tp CPAN, I
suggest making it work with InflateColumn::FS instead (or at least in
addition to InflateColumn::File).

I have tried that with InflateColumn::File, but without success, but in
any case, the most important changes were to make it work with
HTML::FormFu and to be able to do all the operations to the file
(add/modify/delete), and for beeing able to also do the delete, I need
to be able to get the file upload field even if it is empty.

Watch out for the delete method in IC::File; it's broken. At least it was broken for my usage. And that was pretty much a deal breaker for me; that's what got me started on this journey.


Hmm, sounds like I may have just volunteered for Cookbook doc patch, or at least an entry on my blog so others can benefit from my pain. Does this sound like something that should go in the DBIC cookbook?


Charlie

--
   Ꮚ Charlie Garrison ♊ <[email protected]>
   〠 PO Box 141, Windsor, NSW 2756, Australia

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
http://www.ietf.org/rfc/rfc1855.txt

_______________________________________________
List: [email protected]
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/[email protected]/
Dev site: http://dev.catalyst.perl.org/

Reply via email to