Using yaml to configure default options for Paperclip
I love Paperclip. It's an awesome tool for a part of web development which has always been annoying. Now I'm waiting on sending email to get less annoying, (although Rails 3 might take care of that. Might.)
Anyway, the only thing I don't like about Paperclip is the default setting for url and path. Which is currently "/system/:attachment/:id/:style/:filename".
Do you see the problem? I use capistrano so the "/system" doesn't bother me. My problem is the lack of :class. Without :class any attachments with the same name will collide and equal ids in different models will overwrite each other.
Why shouldn't my Album have a cover image and my Book have a cover image?
In Paperclip you can send in custom options to every attachment you have a la:
1 2 3 4 5 6 7 8 9 10 11 |
has_attached_file :logo, :styles => { :tiny => "35x35", :preview => "175x175", :large => "300x300" }, :storage => Rails.env.production? ? :s3 : :filesystem, :s3_credentials => "#{RAILS_ROOT}/config/s3.yml", :path => Rails.env.production? ? ":attachment/:id/:style.:extension" : "#{RAILS_ROOT}/public/uploads/:attachment/:id/:style.:extension", :url => Rails.env.production? ? ":attachment/:id/:style.:extension" : "/uploads/:attachment/:id/:style.:extension", :bucket => 'organization_logos' |
But I don't like typing all that. And wait, there's more. See me using
1 |
Rails.env.production? ? blah : blah
|
I use S3 in production and my filesystem for dev and testing. But I don't like typing that either. I'd rather make a yml file that looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
development: &non_production_settings url: "/system/:class/:attachment/:id/:basename-:style.:extension" path: ":rails_root/public:url" test: url: "/system/:class/:attachment/:id/:basename-:style.:extension" path: ":rails_root/public:url" staging: url: "/system/:class/:attachment/:id/:basename-:style.:extension" path: ":rails_root/public:url" production: url: "/system/:class/:attachment/:id/:basename-:style.:extension" path: ":rails_root/public:url" storage: ":s3" bucket: "my-bucket" |
To do that I just made an initializer that redefines the Paperclip::Attachment.default_options method:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
module Paperclip class Attachment def self.default_options return @default_options if @default_options @default_options = { :url => "/system/:attachment/:id/:style/:filename", :path => ":rails_root/public:url", :styles => {}, :processors => [:thumbnail], :convert_options => {}, :default_url => "/:attachment/:style/missing.png", :default_style => :original, :storage => :filesystem, :whiny => Paperclip.options[:whiny] || Paperclip.options[:whiny_thumbnails] } if defined?(RAILS_ROOT) and File.exists?("#{RAILS_ROOT}/config/paperclip.yml") @default_options.merge!(YAML.load_file("#{RAILS_ROOT}/config/paperclip.yml")[RAILS_ENV].symbolize_keys) end end end end |
Done, let the DRYness begin. You'll have to change the yml file of course.