# Paperclip allows file attachments that are stored in the filesystem. All graphical # transformations are done using the Graphics/ImageMagick command line utilities and # are stored in Tempfiles until the record is saved. Paperclip does not require a # separate model for storing the attachment's information, instead adding a few simple # columns to your table. # # Author:: Jon Yurek # Copyright:: Copyright (c) 2008-2011 thoughtbot, inc. # License:: MIT License (http://www.opensource.org/licenses/mit-license.php) # # Paperclip defines an attachment as any file, though it makes special considerations # for image files. You can declare that a model has an attached file with the # +has_attached_file+ method: # # class User < ActiveRecord::Base # has_attached_file :avatar, :styles => { :thumb => "100x100" } # end # # user = User.new # user.avatar = params[:user][:avatar] # user.avatar.url # # => "/users/avatars/4/original_me.jpg" # user.avatar.url(:thumb) # # => "/users/avatars/4/thumb_me.jpg" # # See the +has_attached_file+ documentation for more details. require 'erb' require 'digest' require 'tempfile' require 'paperclip/version' require 'paperclip/geometry' require 'paperclip/processor' require 'paperclip/tempfile' require 'paperclip/thumbnail' require 'paperclip/interpolations' require 'paperclip/style' require 'paperclip/attachment' require 'paperclip/attachment_options' require 'paperclip/storage' require 'paperclip/callbacks' require 'paperclip/glue' require 'paperclip/errors' require 'paperclip/missing_attachment_styles' require 'paperclip/validators' require 'paperclip/instance_methods' require 'paperclip/logger' require 'paperclip/helpers' require 'paperclip/railtie' require 'mime/types' require 'logger' require 'cocaine' # The base module that gets included in ActiveRecord::Base. See the # documentation for Paperclip::ClassMethods for more useful information. module Paperclip extend Helpers extend Logger extend ProcessorHelpers # Provides configurability to Paperclip. The options available are: # * whiny: Will raise an error if Paperclip cannot process thumbnails of # an uploaded image. Defaults to true. # * log: Logs progress to the Rails log. Uses ActiveRecord's logger, so honors # log levels, etc. Defaults to true. # * command_path: Defines the path at which to find the command line # programs if they are not visible to Rails the system's search path. Defaults to # nil, which uses the first executable found in the user's search path. def self.options @options ||= { :whiny => true, :image_magick_path => nil, :command_path => nil, :log => true, :log_command => true, :swallow_stderr => true } end def self.io_adapters=(new_registry) @io_adapters = new_registry end def self.io_adapters @io_adapters ||= Paperclip::AdapterRegistry.new end module ClassMethods # +has_attached_file+ gives the class it is called on an attribute that maps to a file. This # is typically a file stored somewhere on the filesystem and has been uploaded by a user. # The attribute returns a Paperclip::Attachment object which handles the management of # that file. The intent is to make the attachment as much like a normal attribute. The # thumbnails will be created when the new file is assigned, but they will *not* be saved # until +save+ is called on the record. Likewise, if the attribute is set to +nil+ is # called on it, the attachment will *not* be deleted until +save+ is called. See the # Paperclip::Attachment documentation for more specifics. There are a number of options # you can set to change the behavior of a Paperclip attachment: # * +url+: The full URL of where the attachment is publically accessible. This can just # as easily point to a directory served directly through Apache as it can to an action # that can control permissions. You can specify the full domain and path, but usually # just an absolute path is sufficient. The leading slash *must* be included manually for # absolute paths. The default value is # "/system/:attachment/:id/:style/:filename". See # Paperclip::Attachment#interpolate for more information on variable interpolaton. # :url => "/:class/:attachment/:id/:style_:filename" # :url => "http://some.other.host/stuff/:class/:id_:extension" # * +default_url+: The URL that will be returned if there is no attachment assigned. # This field is interpolated just as the url is. The default value is # "/:attachment/:style/missing.png" # has_attached_file :avatar, :default_url => "/images/default_:style_avatar.png" # User.new.avatar_url(:small) # => "/images/default_small_avatar.png" # * +styles+: A hash of thumbnail styles and their geometries. You can find more about # geometry strings at the ImageMagick website # (http://www.imagemagick.org/script/command-line-options.php#resize). Paperclip # also adds the "#" option (e.g. "50x50#"), which will resize the image to fit maximally # inside the dimensions and then crop the rest off (weighted at the center). The # default value is to generate no thumbnails. # * +default_style+: The thumbnail style that will be used by default URLs. # Defaults to +original+. # has_attached_file :avatar, :styles => { :normal => "100x100#" }, # :default_style => :normal # user.avatar.url # => "/avatars/23/normal_me.png" # * +keep_old_files+: Keep the existing attachment files (original + resized) from # being automatically deleted when an attachment is cleared or updated. # Defaults to +false+.# # * +whiny+: Will raise an error if Paperclip cannot post_process an uploaded file due # to a command line error. This will override the global setting for this attachment. # Defaults to true. # * +convert_options+: When creating thumbnails, use this free-form options # array to pass in various convert command options. Typical options are "-strip" to # remove all Exif data from the image (save space for thumbnails and avatars) or # "-depth 8" to specify the bit depth of the resulting conversion. See ImageMagick # convert documentation for more options: (http://www.imagemagick.org/script/convert.php) # Note that this option takes a hash of options, each of which correspond to the style # of thumbnail being generated. You can also specify :all as a key, which will apply # to all of the thumbnails being generated. If you specify options for the :original, # it would be best if you did not specify destructive options, as the intent of keeping # the original around is to regenerate all the thumbnails when requirements change. # has_attached_file :avatar, :styles => { :large => "300x300", :negative => "100x100" } # :convert_options => { # :all => "-strip", # :negative => "-negate" # } # NOTE: While not deprecated yet, it is not recommended to specify options this way. # It is recommended that :convert_options option be included in the hash passed to each # :styles for compatibility with future versions. # NOTE: Strings supplied to :convert_options are split on space in order to undergo # shell quoting for safety. If your options require a space, please pre-split them # and pass an array to :convert_options instead. # * +storage+: Chooses the storage backend where the files will be stored. The current # choices are :filesystem, :fog and :s3. The default is :filesystem. Make sure you read the # documentation for Paperclip::Storage::Filesystem, Paperclip::Storage::Fog and Paperclip::Storage::S3 # for backend-specific options. # # It's also possible for you to dynamically define your interpolation string for :url, # :default_url, and :path in your model by passing a method name as a symbol as a argument # for your has_attached_file definition: # # class Person # has_attached_file :avatar, :default_url => :default_url_by_gender # # private # # def default_url_by_gender # "/assets/avatars/default_#{gender}.png" # end # end def has_attached_file(name, options = {}) include InstanceMethods if attachment_definitions.nil? self.attachment_definitions = {} else self.attachment_definitions = self.attachment_definitions.dup end attachment_definitions[name] = Paperclip::AttachmentOptions.new(options) Paperclip.classes_with_attachments << self.name Paperclip.check_for_url_clash(name,attachment_definitions[name][:url],self.name) after_save :save_attached_files before_destroy :prepare_for_destroy after_destroy :destroy_attached_files define_paperclip_callbacks :post_process, :"#{name}_post_process" define_method name do |*args| a = attachment_for(name) (args.length > 0) ? a.to_s(args.first) : a end define_method "#{name}=" do |file| attachment_for(name).assign(file) end define_method "#{name}?" do attachment_for(name).file? end validates_each(name) do |record, attr, value| attachment = record.attachment_for(name) attachment.send(:flush_errors) end end # Returns the attachment definitions defined by each call to # has_attached_file. def attachment_definitions self.attachment_definitions end end end # This stuff needs to be run after Paperclip is defined. require 'paperclip/io_adapters/registry' require 'paperclip/io_adapters/identity_adapter' require 'paperclip/io_adapters/file_adapter' require 'paperclip/io_adapters/stringio_adapter' require 'paperclip/io_adapters/nil_adapter' require 'paperclip/io_adapters/attachment_adapter' require 'paperclip/io_adapters/uploaded_file_adapter'