Posted by sebastian.martinez
on February 10, 2010
I was working lately on a Sinatra project, and got fascinated on how fast you can get things up and running.
Everything was beautiful, until I tried to upload a file using paperclip.
Although Paperclip was originally built for rails [Ken Robertson](http://invalidlogic.com/dm-paperclip/) ported it to Datamapper.
Let me explain in few steps how you can upload with Paperclip, using Datamapper.
Start declaring your model like this:
class Resource
include DataMapper::Resource
include Paperclip::Resource
property :id, Serial
has_attached_file :file,
:url => "/system/:attachment/:id/:style/:basename.:extension",
:path => "#{APP_ROOT}/public/system/:attachment/:id/:style/:basename.:extension"
end
You'll need to specify your :url and :path options as the ones built into dm-paperclip are merb centric which won't quite work. Also set APP_ROOT to where ever your application root directory with your static Sinatra folder is.
Now your routes should look something like this:
post '/upload' do
resource = Resource.new(:file => make_paperclip_mash(params[:file]))
halt "There were some errors processing your request..." unless resource.save
end
And there's the tricky part, on the **make_paperclip_mash** method.
Paperclip expects the file object loaded from the form to be in a different form than what is created by default. To fix this you should create a Mash (which is just a Hash, unless you're actually using merb):
def make_paperclip_mash(file_hash)
mash = Mash.new
mash['tempfile'] = file_hash[:tempfile]
mash['filename'] = file_hash[:filename]
mash['content_type'] = file_hash[:type]
mash['size'] = file_hash[:tempfile].size
mash
end
And that's it, now you can upload files using Paperclip right on your Sinatra app with Datamapper.
You can check out the code of this example at: [sinatra_paperclip.rb](http://gist.github.com/291877)
Posted by santiago.pastorino
on July 13, 2009
While developing an application with Sebastián that allow users to upload videos with some file name restrictions, meaning that it must contain only A-Z and 0-9 digits, underscores (_) as a valid component as well, and also the name must be preceded by it's own #id, we came up with the need of applying this custom filter to each uploaded video.
After doing some research on paperclip source code and internet tutorials, we suggest the following solution:
class Video < ActiveRecord::Base
has_attached_file :video,
:path => ":rails_root/public/system/:attachment/:id/:style/:normalized_video_file_name",
:url => "/system/:attachment/:id/:style/:normalized_video_file_name"
Paperclip.interpolates :normalized_video_file_name do |attachment, style|
attachment.instance.normalized_video_file_name
end
def normalized_video_file_name
"#{self.id}-#{self.video_file_name.gsub( /[^a-zA-Z0-9_\.]/, '_')}"
end
end
What are we doing here? Easy, in **has_attached_file** we edit the way paperclip returns the **path** and **url** by default, the most relevant components when saving and loading the file in order to display it.
Paperclip default values are:
path default => ":rails_root/public/system/:attachment/:id/:style/:filename"
url default => "/system/:attachment/:id/:style/:filename"
Values preceded by ':' are the standard interpolations paperclip has. For further information on this visit [http://wiki.github.com/thoughtbot/paperclip/interpolations(Interpolations)](http://wiki.github.com/thoughtbot/paperclip/interpolations.)
What we did was change **:filename** with **:normalized_video_file_name** in both path and url, being the second a custom interpolation and then added the 'normalized_video_file_name' method to video.rb.
By doing this we not only achieve a way for paperclip to handle the file by this normalized way, but also have a method to access the normalized file name, plus being able to access the original file name through paperclip video_file_name method.
So remember on video_file_name you have the uploaded filename and on normalized_video_file_name you have the server filename.