So there’s been a bit of activity on the Paperclip front. I’ve added Amazon S3 support using the RightAWS gem. Some fellow githubbers have contributed some patches to fix up said S3 support, as well as to add more (and better) validations for content type, etc. We’ve brought it up to a nice, round v2.1.2 as of yesterday. Give yourselves a round of applause.
I highly encourage you to give it a whirl if you haven’t already. It’s very easy to both get and to use!
An interesting note!
Ken Robertson has gone to great lengths to port Paperclip to DataMapper, which should be great news for all you Merbers out there. He’s kept it quite up-to-date, and it’s right alongside the 2.1.2 current release. Hopefully we’ll be able to merge codebases in the future, though right now there’s enough of a difference between DM and AR to make that not terribly feasible.
Here’s a handy tip!
One of the most frequently asked questions is how to use data from your instances in the path and/or URL. The answer is the interpolations hash, which is quite user-extensible. Let’s say you had a song that played in the background of each User’s profile (making this exercise purely hypothetical, of course), and you wanted its name to be the same as the User’s username.
One really good way of allowing this functionality would be to add the following to your config/initializers/paperclip.rb file:
Paperclip::Attachment.interpolations[:username] = proc do |attachment, style|
attachment.instance.login # or whatever you've named your User's login/username/etc. attribute
end
The #instance method is the instance of the model that this attachment is attached to. You can access any of the model’s attributes, methods, associations, and so on from that object just like normal. Also note that you don’t have to name your interpolation the same thing as the attribute you’re interpolating (though it helps clarity).
Now you can add this to your :path and :url parameters like so:
class User < ActiveRecord::Base
has_attached_file :song,
:path => ":rails_root/public/system/:attachment/:username.:extension",
:url => "/:attachment/:username.:extension"
end
When you call #url or #path on your attachment, Paperclip will run through the interpolations hash, find strings that match its keys, and replace them with the return values of the procs. In this case, you’d produce a lovely url of ”/songs/jyurek.mp3”
It’s a very easy way to add flexibility to your files’ names without having to modify any code yourself.
Another handy tip!
S3 support is now baked in! The updated has_attached_file call looks kinda like this one does:
class House < ActiveRecord::Base
has_attached_file :blueprint,
:styles => { :thumbnail => "150x150" },
:path => ":attachment/:id/:style.:extension",
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:bucket => "bucket-of-holding"
end
Please note the additional options, including:
:storage: Specify :s3 here to use S3. Strictly speaking you could specify :filesystem here if you’re using the filesystem, but it’s the default so don’t bother.:s3_credentials: You should give this a Hash, a path to a file, or a File object. The File should contain a YAML-ized Hash, and the contents of the Hash should be the access_key_id and secret_access_key used to access your S3 account. You can also “environment-space” these inside the hash, just like your database.yml file.:bucket: The name of the S3 bucket that will be holding your data.Note that there’s no :url option. That’s because the S3 URLs are generated from the bucket and the path name, so you don’t have to worry about them. You can also specify permissions for your files, in case you don’t want the default “public-read”, by using :s3_permissions.
You can find more about the S3 Storage options and the Filesystem Storage options at their RDocs.
Keep up to date!
Remember, there’s always the Paperclip Google Group and the Paperclip Lighthouse Account in case you have problems, questions, or feature requests.
Last Update: For archival reasons, I’m removing direct links to releases, etc. from here. All the info you need is at the official paperclip project page.
For some reason, file attachment is annoying. I don’t know why, and I know a lot of people have attempted to solve the problem in the past, myself included. Yet it still is. Having gotten fed up with gotchas and design decisions that we didn’t agree with, I went and wrote Paperclip on the plane to RailsConf last year. We’ve been using it here in various forms since and IMHO it’s the way to handle uploads, and finally decided that it should be released.
class User < ActiveRecord::Base
has_attached_file :avatar,
:styles => { :square => ["64x64#", :png],
:small => "150x150>" }
end
A file is treated like any other attribute. It’s assigned like any other attribute, and it’s not saved until you call #save. It doesn’t have its own model. You can say where it’s saved on the filesystem, and what URL it’s referred to by (which means you can let Apache/nginx handle it or you can route it through the app for permissions/security). You can say what thumbnails are made, what resolution and format they are, and you can actually save cropped square thumbnails without any hassle.
class AddAvatarToUser < ActiveRecord::Migration
def self.up
add_column :users, :avatar_file_name, :string
add_column :users, :avatar_content_type, :string
add_column :users, :avatar_file_size, :integer
end
def self.down; ...; end
end
You don’t need mini_magick (which we’ve found may have been causing issues), you don’t need ImageScience (which, on the first image we tried to upload, failed to decode it, and it was a simple GIF), you don’t need RMagick (which has memory issues that were the impetus for mini_magick in the first place). You just need ImageMagick installed somewhere, which is as easy as yum, apt-get, or port on any system worth hosting on.
And this isn’t just for avatars and images. You can upload anything. No thumbnails are made by default, so it won’t automagically choke on your Excel docs.
In your model:
class User < ActiveRecord::Base
has_attached_file :avatar,
:styles => { :medium => "300x300>",
:thumb => "100x100>" }
end
In your edit and new views:
<% form_for :user, :html => { :multipart => true } do |form| %>
<%= form.file_field :avatar %>
<% end %>
In your controller:
def create
@user = User.create( params[:user] )
end
In your show view:
<%= image_tag @user.avatar.url %>
<%= image_tag @user.avatar.url(:medium) %>
<%= image_tag @user.avatar.url(:thumb) %>
It can’t be everything for everyone, but for the vast majority of cases we’ve come across, this is the right fit. Really, once you use this you’ll wonder why managing files was such a hassle.