[Catalyst] Where is the form field lost?
Charlie Garrison
garrison at zeta.org.au
Mon Jan 25 08:28:01 GMT 2010
Good evening,
On 25/01/10 at 8:08 AM +0200, orasnita at gmail.com wrote:
>From: "Charlie Garrison" <garrison at zeta.org.au>
>On 24/01/10 at 10:47 PM +0200, Octavian Rasnita <orasnita at gmail.com> 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 ♊ <garrison at zeta.org.au>
〠 PO Box 141, Windsor, NSW 2756, Australia
O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
http://www.ietf.org/rfc/rfc1855.txt
More information about the Catalyst
mailing list