paperclip 2.4.2 → 2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of paperclip might be problematic. Click here for more details.
- data/Rakefile +1 -1
- data/lib/paperclip.rb +5 -2
- data/lib/paperclip/attachment.rb +38 -56
- data/lib/paperclip/geometry.rb +6 -4
- data/lib/paperclip/missing_attachment_styles.rb +2 -1
- data/lib/paperclip/options.rb +78 -0
- data/lib/paperclip/storage/fog.rb +21 -15
- data/lib/paperclip/storage/s3.rb +28 -25
- data/lib/paperclip/style.rb +3 -3
- data/lib/paperclip/version.rb +1 -1
- data/test/attachment_test.rb +16 -29
- data/test/fog_test.rb +4 -4
- data/test/geometry_test.rb +1 -1
- data/test/helper.rb +1 -0
- data/test/options_test.rb +68 -0
- data/test/paperclip_missing_attachment_styles_test.rb +1 -1
- data/test/storage/s3_test.rb +12 -4
- data/test/style_test.rb +22 -28
- metadata +111 -164
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/paperclip.rb
    CHANGED
    
    | @@ -28,6 +28,7 @@ | |
| 28 28 | 
             
            require 'erb'
         | 
| 29 29 | 
             
            require 'digest'
         | 
| 30 30 | 
             
            require 'tempfile'
         | 
| 31 | 
            +
            require 'paperclip/options'
         | 
| 31 32 | 
             
            require 'paperclip/version'
         | 
| 32 33 | 
             
            require 'paperclip/upfile'
         | 
| 33 34 | 
             
            require 'paperclip/iostream'
         | 
| @@ -137,8 +138,10 @@ module Paperclip | |
| 137 138 | 
             
                  @known_processors[name.to_s] = processor
         | 
| 138 139 | 
             
                end
         | 
| 139 140 |  | 
| 141 | 
            +
                # Find all instances of the given Active Record model +klass+ with attachment +name+.
         | 
| 142 | 
            +
                # This method is used by the refresh rake tasks.
         | 
| 140 143 | 
             
                def each_instance_with_attachment(klass, name)
         | 
| 141 | 
            -
                  class_for(klass).all.each do |instance|
         | 
| 144 | 
            +
                  class_for(klass).find(:all, :order => 'id').each do |instance|
         | 
| 142 145 | 
             
                    yield(instance) if instance.send(:"#{name}?")
         | 
| 143 146 | 
             
                  end
         | 
| 144 147 | 
             
                end
         | 
| @@ -317,7 +320,7 @@ module Paperclip | |
| 317 320 | 
             
                  end
         | 
| 318 321 |  | 
| 319 322 | 
             
                  attachment_definitions[name] = {:validations => []}.merge(options)
         | 
| 320 | 
            -
                  Paperclip.classes_with_attachments << self | 
| 323 | 
            +
                  Paperclip.classes_with_attachments << self.name
         | 
| 321 324 | 
             
                  Paperclip.check_for_url_clash(name,attachment_definitions[name][:url],self.name)
         | 
| 322 325 |  | 
| 323 326 | 
             
                  after_save :save_attached_files
         | 
    
        data/lib/paperclip/attachment.rb
    CHANGED
    
    | @@ -29,7 +29,7 @@ module Paperclip | |
| 29 29 | 
             
                  }
         | 
| 30 30 | 
             
                end
         | 
| 31 31 |  | 
| 32 | 
            -
                attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny, :options, : | 
| 32 | 
            +
                attr_reader :name, :instance, :default_style, :convert_options, :queued_for_write, :whiny, :options, :interpolator
         | 
| 33 33 | 
             
                attr_accessor :post_processing
         | 
| 34 34 |  | 
| 35 35 | 
             
                # Creates an Attachment object. +name+ is the name of the attachment,
         | 
| @@ -62,27 +62,7 @@ module Paperclip | |
| 62 62 |  | 
| 63 63 | 
             
                  options = self.class.default_options.merge(options)
         | 
| 64 64 |  | 
| 65 | 
            -
                  @ | 
| 66 | 
            -
                  @url                   = @url.call(self) if @url.is_a?(Proc)
         | 
| 67 | 
            -
                  @path                  = options[:path]
         | 
| 68 | 
            -
                  @path                  = @path.call(self) if @path.is_a?(Proc)
         | 
| 69 | 
            -
                  @styles                = options[:styles]
         | 
| 70 | 
            -
                  @only_process          = options[:only_process]
         | 
| 71 | 
            -
                  @normalized_styles     = nil
         | 
| 72 | 
            -
                  @default_url           = options[:default_url]
         | 
| 73 | 
            -
                  @default_style         = options[:default_style]
         | 
| 74 | 
            -
                  @storage               = options[:storage]
         | 
| 75 | 
            -
                  @use_timestamp         = options[:use_timestamp]
         | 
| 76 | 
            -
                  @whiny                 = options[:whiny_thumbnails] || options[:whiny]
         | 
| 77 | 
            -
                  @use_default_time_zone = options[:use_default_time_zone]
         | 
| 78 | 
            -
                  @hash_digest           = options[:hash_digest]
         | 
| 79 | 
            -
                  @hash_data             = options[:hash_data]
         | 
| 80 | 
            -
                  @hash_secret           = options[:hash_secret]
         | 
| 81 | 
            -
                  @convert_options       = options[:convert_options]
         | 
| 82 | 
            -
                  @source_file_options   = options[:source_file_options]
         | 
| 83 | 
            -
                  @processors            = options[:processors]
         | 
| 84 | 
            -
                  @preserve_files        = options[:preserve_files]
         | 
| 85 | 
            -
                  @options               = options
         | 
| 65 | 
            +
                  @options               = Paperclip::Options.new(self, options)
         | 
| 86 66 | 
             
                  @post_processing       = true
         | 
| 87 67 | 
             
                  @queued_for_delete     = []
         | 
| 88 68 | 
             
                  @queued_for_write      = {}
         | 
| @@ -93,19 +73,13 @@ module Paperclip | |
| 93 73 | 
             
                  initialize_storage
         | 
| 94 74 | 
             
                end
         | 
| 95 75 |  | 
| 96 | 
            -
                 | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                  @normalized_styles
         | 
| 104 | 
            -
                end
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                def processors
         | 
| 107 | 
            -
                  @processors.respond_to?(:call) ? @processors.call(instance) : @processors
         | 
| 108 | 
            -
                end
         | 
| 76 | 
            +
                # [:url, :path, :only_process, :normalized_styles, :default_url, :default_style,
         | 
| 77 | 
            +
                #  :storage, :use_timestamp, :whiny, :use_default_time_zone, :hash_digest, :hash_secret,
         | 
| 78 | 
            +
                #  :convert_options, :preserve_files].each do |field|
         | 
| 79 | 
            +
                #   define_method field do
         | 
| 80 | 
            +
                #     @options.send(field)
         | 
| 81 | 
            +
                #   end
         | 
| 82 | 
            +
                # end
         | 
| 109 83 |  | 
| 110 84 | 
             
                # What gets called when you call instance.attachment = File. It clears
         | 
| 111 85 | 
             
                # errors, assigns attributes, and processes the file. It
         | 
| @@ -139,7 +113,7 @@ module Paperclip | |
| 139 113 |  | 
| 140 114 | 
             
                  @dirty = true
         | 
| 141 115 |  | 
| 142 | 
            -
                  post_process(*@only_process) if post_processing
         | 
| 116 | 
            +
                  post_process(*@options.only_process) if post_processing
         | 
| 143 117 |  | 
| 144 118 | 
             
                  # Reset the file size if the original file was reprocessed.
         | 
| 145 119 | 
             
                  instance_write(:file_size,   @queued_for_write[:original].size.to_i)
         | 
| @@ -154,9 +128,9 @@ module Paperclip | |
| 154 128 | 
             
                # grained security.  This is not recommended if you don't need the
         | 
| 155 129 | 
             
                # security, however, for performance reasons. Set use_timestamp to false
         | 
| 156 130 | 
             
                # if you want to stop the attachment update time appended to the url
         | 
| 157 | 
            -
                def url(style_name = default_style, use_timestamp = @use_timestamp)
         | 
| 158 | 
            -
                  default_url = @default_url.is_a?(Proc) ? @default_url.call(self) : @default_url
         | 
| 159 | 
            -
                  url = original_filename.nil? ? interpolate(default_url, style_name) : interpolate(@url, style_name)
         | 
| 131 | 
            +
                def url(style_name = default_style, use_timestamp = @options.use_timestamp)
         | 
| 132 | 
            +
                  default_url = @options.default_url.is_a?(Proc) ? @options.default_url.call(self) : @options.default_url
         | 
| 133 | 
            +
                  url = original_filename.nil? ? interpolate(default_url, style_name) : interpolate(@options.url, style_name)
         | 
| 160 134 | 
             
                  URI.escape(use_timestamp && updated_at ? [url, updated_at].compact.join(url.include?("?") ? "&" : "?") : url)
         | 
| 161 135 | 
             
                end
         | 
| 162 136 |  | 
| @@ -165,7 +139,7 @@ module Paperclip | |
| 165 139 | 
             
                # on disk. If the file is stored in S3, the path is the "key" part of the
         | 
| 166 140 | 
             
                # URL, and the :bucket option refers to the S3 bucket.
         | 
| 167 141 | 
             
                def path(style_name = default_style)
         | 
| 168 | 
            -
                  original_filename.nil? ? nil : interpolate(@path, style_name)
         | 
| 142 | 
            +
                  original_filename.nil? ? nil : interpolate(@options.path, style_name)
         | 
| 169 143 | 
             
                end
         | 
| 170 144 |  | 
| 171 145 | 
             
                # Alias to +url+
         | 
| @@ -173,6 +147,14 @@ module Paperclip | |
| 173 147 | 
             
                  url(style_name)
         | 
| 174 148 | 
             
                end
         | 
| 175 149 |  | 
| 150 | 
            +
                def default_style
         | 
| 151 | 
            +
                  @options.default_style
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def styles
         | 
| 155 | 
            +
                  @options.styles
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 176 158 | 
             
                # Returns an array containing the errors on this attachment.
         | 
| 177 159 | 
             
                def errors
         | 
| 178 160 | 
             
                  @errors
         | 
| @@ -205,7 +187,7 @@ module Paperclip | |
| 205 187 | 
             
                # nil to the attachment *and saving*. This is permanent. If you wish to
         | 
| 206 188 | 
             
                # wipe out the existing attachment but not save, use #clear.
         | 
| 207 189 | 
             
                def destroy
         | 
| 208 | 
            -
                  unless @preserve_files
         | 
| 190 | 
            +
                  unless @options.preserve_files
         | 
| 209 191 | 
             
                    clear
         | 
| 210 192 | 
             
                    save
         | 
| 211 193 | 
             
                  end
         | 
| @@ -245,16 +227,16 @@ module Paperclip | |
| 245 227 | 
             
                # The time zone to use for timestamp interpolation.  Using the default
         | 
| 246 228 | 
             
                # time zone ensures that results are consistent across all threads.
         | 
| 247 229 | 
             
                def time_zone
         | 
| 248 | 
            -
                  @use_default_time_zone ? Time.zone_default : Time.zone
         | 
| 230 | 
            +
                  @options.use_default_time_zone ? Time.zone_default : Time.zone
         | 
| 249 231 | 
             
                end
         | 
| 250 232 |  | 
| 251 233 | 
             
                # Returns a unique hash suitable for obfuscating the URL of an otherwise
         | 
| 252 234 | 
             
                # publicly viewable attachment.
         | 
| 253 235 | 
             
                def hash(style_name = default_style)
         | 
| 254 | 
            -
                  raise ArgumentError, "Unable to generate hash without :hash_secret" unless @hash_secret
         | 
| 236 | 
            +
                  raise ArgumentError, "Unable to generate hash without :hash_secret" unless @options.hash_secret
         | 
| 255 237 | 
             
                  require 'openssl' unless defined?(OpenSSL)
         | 
| 256 | 
            -
                  data = interpolate(@hash_data, style_name)
         | 
| 257 | 
            -
                  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@hash_digest).new, @hash_secret, data)
         | 
| 238 | 
            +
                  data = interpolate(@options.hash_data, style_name)
         | 
| 239 | 
            +
                  OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get(@options.hash_digest).new, @options.hash_secret, data)
         | 
| 258 240 | 
             
                end
         | 
| 259 241 |  | 
| 260 242 | 
             
                def generate_fingerprint(source)
         | 
| @@ -352,28 +334,28 @@ module Paperclip | |
| 352 334 | 
             
                end
         | 
| 353 335 |  | 
| 354 336 | 
             
                def initialize_storage #:nodoc:
         | 
| 355 | 
            -
                  storage_class_name = @storage.to_s.downcase.camelize
         | 
| 337 | 
            +
                  storage_class_name = @options.storage.to_s.downcase.camelize
         | 
| 356 338 | 
             
                  begin
         | 
| 357 | 
            -
                     | 
| 339 | 
            +
                    storage_module = Paperclip::Storage.const_get(storage_class_name)
         | 
| 358 340 | 
             
                  rescue NameError
         | 
| 359 341 | 
             
                    raise StorageMethodNotFound, "Cannot load storage module '#{storage_class_name}'"
         | 
| 360 342 | 
             
                  end
         | 
| 361 | 
            -
                  self.extend( | 
| 343 | 
            +
                  self.extend(storage_module)
         | 
| 362 344 | 
             
                end
         | 
| 363 345 |  | 
| 364 346 | 
             
                def extra_options_for(style) #:nodoc:
         | 
| 365 | 
            -
                  all_options   = convert_options[:all]
         | 
| 347 | 
            +
                  all_options   = @options.convert_options[:all]
         | 
| 366 348 | 
             
                  all_options   = all_options.call(instance)   if all_options.respond_to?(:call)
         | 
| 367 | 
            -
                  style_options = convert_options[style]
         | 
| 349 | 
            +
                  style_options = @options.convert_options[style]
         | 
| 368 350 | 
             
                  style_options = style_options.call(instance) if style_options.respond_to?(:call)
         | 
| 369 351 |  | 
| 370 352 | 
             
                  [ style_options, all_options ].compact.join(" ")
         | 
| 371 353 | 
             
                end
         | 
| 372 354 |  | 
| 373 355 | 
             
                def extra_source_file_options_for(style) #:nodoc:
         | 
| 374 | 
            -
                  all_options   = source_file_options[:all]
         | 
| 356 | 
            +
                  all_options   = @options.source_file_options[:all]
         | 
| 375 357 | 
             
                  all_options   = all_options.call(instance)   if all_options.respond_to?(:call)
         | 
| 376 | 
            -
                  style_options = source_file_options[style]
         | 
| 358 | 
            +
                  style_options = @options.source_file_options[style]
         | 
| 377 359 | 
             
                  style_options = style_options.call(instance) if style_options.respond_to?(:call)
         | 
| 378 360 |  | 
| 379 361 | 
             
                  [ style_options, all_options ].compact.join(" ")
         | 
| @@ -389,7 +371,7 @@ module Paperclip | |
| 389 371 | 
             
                end
         | 
| 390 372 |  | 
| 391 373 | 
             
                def post_process_styles(*style_args) #:nodoc:
         | 
| 392 | 
            -
                  styles.each do |name, style|
         | 
| 374 | 
            +
                  @options.styles.each do |name, style|
         | 
| 393 375 | 
             
                    begin
         | 
| 394 376 | 
             
                      if style_args.empty? || style_args.include?(name)
         | 
| 395 377 | 
             
                        raise RuntimeError.new("Style #{name} has no processors defined.") if style.processors.blank?
         | 
| @@ -399,7 +381,7 @@ module Paperclip | |
| 399 381 | 
             
                      end
         | 
| 400 382 | 
             
                    rescue PaperclipError => e
         | 
| 401 383 | 
             
                      log("An error was received while processing: #{e.inspect}")
         | 
| 402 | 
            -
                      (@errors[:processing] ||= []) << e.message if @whiny
         | 
| 384 | 
            +
                      (@errors[:processing] ||= []) << e.message if @options.whiny
         | 
| 403 385 | 
             
                    end
         | 
| 404 386 | 
             
                  end
         | 
| 405 387 | 
             
                end
         | 
| @@ -409,8 +391,8 @@ module Paperclip | |
| 409 391 | 
             
                end
         | 
| 410 392 |  | 
| 411 393 | 
             
                def queue_existing_for_delete #:nodoc:
         | 
| 412 | 
            -
                  return  | 
| 413 | 
            -
                  @queued_for_delete += [:original,  | 
| 394 | 
            +
                  return if @options.preserve_files || !file?
         | 
| 395 | 
            +
                  @queued_for_delete += [:original, *@options.styles.keys].uniq.map do |style|
         | 
| 414 396 | 
             
                    path(style) if exists?(style)
         | 
| 415 397 | 
             
                  end.compact
         | 
| 416 398 | 
             
                  instance_write(:file_name, nil)
         | 
    
        data/lib/paperclip/geometry.rb
    CHANGED
    
    | @@ -13,18 +13,20 @@ module Paperclip | |
| 13 13 |  | 
| 14 14 | 
             
                # Uses ImageMagick to determing the dimensions of a file, passed in as either a
         | 
| 15 15 | 
             
                # File or path.
         | 
| 16 | 
            +
                # NOTE: (race cond) Do not reassign the 'file' variable inside this method as it is likely to be
         | 
| 17 | 
            +
                # a Tempfile object, which would be eligible for file deletion when no longer referenced.
         | 
| 16 18 | 
             
                def self.from_file file
         | 
| 17 | 
            -
                   | 
| 18 | 
            -
                  raise(Paperclip::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name")) if  | 
| 19 | 
            +
                  file_path = file.respond_to?(:path) ? file.path : file
         | 
| 20 | 
            +
                  raise(Paperclip::NotIdentifiedByImageMagickError.new("Cannot find the geometry of a file with a blank name")) if file_path.blank?
         | 
| 19 21 | 
             
                  geometry = begin
         | 
| 20 | 
            -
                               Paperclip.run("identify", "-format %wx%h :file", :file => "#{ | 
| 22 | 
            +
                               Paperclip.run("identify", "-format %wx%h :file", :file => "#{file_path}[0]")
         | 
| 21 23 | 
             
                             rescue Cocaine::ExitStatusError
         | 
| 22 24 | 
             
                               ""
         | 
| 23 25 | 
             
                             rescue Cocaine::CommandNotFoundError => e
         | 
| 24 26 | 
             
                               raise Paperclip::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
         | 
| 25 27 | 
             
                             end
         | 
| 26 28 | 
             
                  parse(geometry) ||
         | 
| 27 | 
            -
                    raise(NotIdentifiedByImageMagickError.new("#{ | 
| 29 | 
            +
                    raise(NotIdentifiedByImageMagickError.new("#{file_path} is not recognized by the 'identify' command."))
         | 
| 28 30 | 
             
                end
         | 
| 29 31 |  | 
| 30 32 | 
             
                # Parses a "WxH" formatted string, where W is the width and H is the height.
         | 
| @@ -38,7 +38,8 @@ module Paperclip | |
| 38 38 | 
             
              #   }
         | 
| 39 39 | 
             
              def self.current_attachments_styles
         | 
| 40 40 | 
             
                Hash.new.tap do |current_styles|
         | 
| 41 | 
            -
                  Paperclip.classes_with_attachments.each do | | 
| 41 | 
            +
                  Paperclip.classes_with_attachments.each do |klass_name|
         | 
| 42 | 
            +
                    klass = Paperclip.class_for(klass_name)
         | 
| 42 43 | 
             
                    klass.attachment_definitions.each do |attachment_name, attachment_attributes|
         | 
| 43 44 | 
             
                      # TODO: is it even possible to take into account Procs?
         | 
| 44 45 | 
             
                      next if attachment_attributes[:styles].kind_of?(Proc)
         | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            module Paperclip
         | 
| 2 | 
            +
              class Options
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                attr_accessor :url, :path, :only_process, :normalized_styles, :default_url, :default_style,
         | 
| 5 | 
            +
                 :storage, :use_timestamp, :whiny, :use_default_time_zone, :hash_digest, :hash_secret,
         | 
| 6 | 
            +
                 :convert_options, :source_file_options, :preserve_files, :http_proxy
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                attr_accessor :s3_credentials, :s3_host_name, :s3_options, :s3_permissions, :s3_protocol,
         | 
| 9 | 
            +
                  :s3_headers, :s3_host_alias, :bucket
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                attr_accessor :fog_directory, :fog_credentials, :fog_host, :fog_public, :fog_file
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def initialize(attachment, hash)
         | 
| 14 | 
            +
                  @attachment            = attachment
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  @url                   = hash[:url]
         | 
| 17 | 
            +
                  @url                   = @url.call(@attachment) if @url.is_a?(Proc)
         | 
| 18 | 
            +
                  @path                  = hash[:path]
         | 
| 19 | 
            +
                  @path                  = @path.call(@attachment) if @path.is_a?(Proc)
         | 
| 20 | 
            +
                  @styles                = hash[:styles]
         | 
| 21 | 
            +
                  @only_process          = hash[:only_process]
         | 
| 22 | 
            +
                  @normalized_styles     = nil
         | 
| 23 | 
            +
                  @default_url           = hash[:default_url]
         | 
| 24 | 
            +
                  @default_style         = hash[:default_style]
         | 
| 25 | 
            +
                  @storage               = hash[:storage]
         | 
| 26 | 
            +
                  @use_timestamp         = hash[:use_timestamp]
         | 
| 27 | 
            +
                  @whiny                 = hash[:whiny_thumbnails] || hash[:whiny]
         | 
| 28 | 
            +
                  @use_default_time_zone = hash[:use_default_time_zone]
         | 
| 29 | 
            +
                  @hash_digest           = hash[:hash_digest]
         | 
| 30 | 
            +
                  @hash_data             = hash[:hash_data]
         | 
| 31 | 
            +
                  @hash_secret           = hash[:hash_secret]
         | 
| 32 | 
            +
                  @convert_options       = hash[:convert_options]
         | 
| 33 | 
            +
                  @source_file_options   = hash[:source_file_options]
         | 
| 34 | 
            +
                  @processors            = hash[:processors]
         | 
| 35 | 
            +
                  @preserve_files        = hash[:preserve_files]
         | 
| 36 | 
            +
                  @http_proxy            = hash[:http_proxy]
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  #s3 options
         | 
| 39 | 
            +
                  @s3_credentials        = hash[:s3_credentials]
         | 
| 40 | 
            +
                  @s3_host_name          = hash[:s3_host_name]
         | 
| 41 | 
            +
                  @bucket                = hash[:bucket]
         | 
| 42 | 
            +
                  @s3_options            = hash[:s3_options]
         | 
| 43 | 
            +
                  @s3_permissions        = hash[:s3_permissions]
         | 
| 44 | 
            +
                  @s3_protocol           = hash[:s3_protocol]
         | 
| 45 | 
            +
                  @s3_headers            = hash[:s3_headers]
         | 
| 46 | 
            +
                  @s3_host_alias         = hash[:s3_host_alias]
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  #fog options
         | 
| 49 | 
            +
                  @fog_directory         = hash[:fog_directory]
         | 
| 50 | 
            +
                  @fog_credentials       = hash[:fog_credentials]
         | 
| 51 | 
            +
                  @fog_host              = hash[:fog_host]
         | 
| 52 | 
            +
                  @fog_public            = hash[:fog_public]
         | 
| 53 | 
            +
                  @fog_file              = hash[:fog_file]
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def method_missing(method, *args, &blk)
         | 
| 57 | 
            +
                  if method.to_s[-1] == "="
         | 
| 58 | 
            +
                    instance_variable_set("@#{method[0..-2]}", args[0])
         | 
| 59 | 
            +
                  else
         | 
| 60 | 
            +
                    instance_variable_get("@#{method}")
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def processors
         | 
| 65 | 
            +
                  @processors.respond_to?(:call) ? @processors.call(@attachment.instance) : @processors
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def styles
         | 
| 69 | 
            +
                  if @styles.respond_to?(:call) || !@normalized_styles
         | 
| 70 | 
            +
                    @normalized_styles = ActiveSupport::OrderedHash.new
         | 
| 71 | 
            +
                    (@styles.respond_to?(:call) ? @styles.call(@attachment) : @styles).each do |name, args|
         | 
| 72 | 
            +
                      normalized_styles[name] = Paperclip::Style.new(name, args.dup, @attachment)
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                  @normalized_styles
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
            end
         | 
| @@ -41,15 +41,9 @@ module Paperclip | |
| 41 41 | 
             
                    end unless defined?(Fog)
         | 
| 42 42 |  | 
| 43 43 | 
             
                    base.instance_eval do
         | 
| 44 | 
            -
                       | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
                      @fog_public       = @options.key?(:fog_public) ? @options[:fog_public] : true
         | 
| 48 | 
            -
                      @fog_file         = @options[:fog_file] || {}
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                      unless @url.to_s.match(/^:fog.*url$/)
         | 
| 51 | 
            -
                        @path  = @path.gsub(/:url/, @url)
         | 
| 52 | 
            -
                        @url   = ':fog_public_url'
         | 
| 44 | 
            +
                      unless @options.url.to_s.match(/^:fog.*url$/)
         | 
| 45 | 
            +
                        @options.path  = @options.path.gsub(/:url/, @options.url)
         | 
| 46 | 
            +
                        @options.url   = ':fog_public_url'
         | 
| 53 47 | 
             
                      end
         | 
| 54 48 | 
             
                      Paperclip.interpolates(:fog_public_url) do |attachment, style|
         | 
| 55 49 | 
             
                        attachment.public_url(style)
         | 
| @@ -65,15 +59,27 @@ module Paperclip | |
| 65 59 | 
             
                    end
         | 
| 66 60 | 
             
                  end
         | 
| 67 61 |  | 
| 62 | 
            +
                  def fog_credentials
         | 
| 63 | 
            +
                    @fog_credentials ||= parse_credentials(@options.fog_credentials)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def fog_file
         | 
| 67 | 
            +
                    @fog_file ||= @options.fog_file || {}
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  def fog_public
         | 
| 71 | 
            +
                    @fog_public ||= @options.fog_public || true
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 68 74 | 
             
                  def flush_writes
         | 
| 69 75 | 
             
                    for style, file in @queued_for_write do
         | 
| 70 76 | 
             
                      log("saving #{path(style)}")
         | 
| 71 77 | 
             
                      retried = false
         | 
| 72 78 | 
             
                      begin
         | 
| 73 | 
            -
                        directory.files.create( | 
| 79 | 
            +
                        directory.files.create(fog_file.merge(
         | 
| 74 80 | 
             
                          :body   => file,
         | 
| 75 81 | 
             
                          :key    => path(style),
         | 
| 76 | 
            -
                          :public =>  | 
| 82 | 
            +
                          :public => fog_public
         | 
| 77 83 | 
             
                        ))
         | 
| 78 84 | 
             
                      rescue Excon::Errors::NotFound
         | 
| 79 85 | 
             
                        raise if retried
         | 
| @@ -115,8 +121,8 @@ module Paperclip | |
| 115 121 | 
             
                  end
         | 
| 116 122 |  | 
| 117 123 | 
             
                  def public_url(style = default_style)
         | 
| 118 | 
            -
                    if @fog_host
         | 
| 119 | 
            -
                      host = (@fog_host =~ /%d/) ? @fog_host % (path(style).hash % 4) : @fog_host
         | 
| 124 | 
            +
                    if @options.fog_host
         | 
| 125 | 
            +
                      host = (@options.fog_host =~ /%d/) ? @options.fog_host % (path(style).hash % 4) : @options.fog_host
         | 
| 120 126 | 
             
                      "#{host}/#{path(style)}"
         | 
| 121 127 | 
             
                    else
         | 
| 122 128 | 
             
                      directory.files.new(:key => path(style)).public_url
         | 
| @@ -145,11 +151,11 @@ module Paperclip | |
| 145 151 | 
             
                  end
         | 
| 146 152 |  | 
| 147 153 | 
             
                  def connection
         | 
| 148 | 
            -
                    @connection ||= ::Fog::Storage.new( | 
| 154 | 
            +
                    @connection ||= ::Fog::Storage.new(fog_credentials)
         | 
| 149 155 | 
             
                  end
         | 
| 150 156 |  | 
| 151 157 | 
             
                  def directory
         | 
| 152 | 
            -
                    @directory ||= connection.directories.new(:key => @fog_directory)
         | 
| 158 | 
            +
                    @directory ||= connection.directories.new(:key => @options.fog_directory)
         | 
| 153 159 | 
             
                  end
         | 
| 154 160 | 
             
                end
         | 
| 155 161 | 
             
              end
         | 
    
        data/lib/paperclip/storage/s3.rb
    CHANGED
    
    | @@ -77,33 +77,28 @@ module Paperclip | |
| 77 77 | 
             
                    end unless defined?(AWS::S3)
         | 
| 78 78 |  | 
| 79 79 | 
             
                    base.instance_eval do
         | 
| 80 | 
            -
                      @ | 
| 81 | 
            -
                      @ | 
| 82 | 
            -
                      @ | 
| 83 | 
            -
                      @bucket         = @bucket.call(self) if @bucket.is_a?(Proc)
         | 
| 84 | 
            -
                      @s3_options     = @options[:s3_options]     || {}
         | 
| 85 | 
            -
                      @s3_permissions = set_permissions(@options[:s3_permissions])
         | 
| 86 | 
            -
                      @s3_protocol    = @options[:s3_protocol]    ||
         | 
| 80 | 
            +
                      @s3_options     = @options.s3_options     || {}
         | 
| 81 | 
            +
                      @s3_permissions = set_permissions(@options.s3_permissions)
         | 
| 82 | 
            +
                      @s3_protocol    = @options.s3_protocol    ||
         | 
| 87 83 | 
             
                        Proc.new do |style|
         | 
| 88 84 | 
             
                          (@s3_permissions[style.to_sym] || @s3_permissions[:default]) == :public_read ? 'http' : 'https'
         | 
| 89 85 | 
             
                        end
         | 
| 90 | 
            -
                      @s3_headers     = @options | 
| 91 | 
            -
             | 
| 92 | 
            -
                       | 
| 93 | 
            -
             | 
| 94 | 
            -
                        @ | 
| 95 | 
            -
                        @url          = ":s3_path_url"
         | 
| 86 | 
            +
                      @s3_headers     = @options.s3_headers     || {}
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      unless @options.url.to_s.match(/^:s3.*url$/) || @options.url == ":asset_host"
         | 
| 89 | 
            +
                        @options.path         = @options.path.gsub(/:url/, @options.url)
         | 
| 90 | 
            +
                        @options.url          = ":s3_path_url"
         | 
| 96 91 | 
             
                      end
         | 
| 97 | 
            -
                      @url | 
| 92 | 
            +
                      @options.url = @options.url.inspect if @options.url.is_a?(Symbol)
         | 
| 98 93 |  | 
| 99 | 
            -
                      @http_proxy = @options | 
| 94 | 
            +
                      @http_proxy = @options.http_proxy || nil
         | 
| 100 95 | 
             
                      if @http_proxy
         | 
| 101 96 | 
             
                        @s3_options.merge!({:proxy => @http_proxy})
         | 
| 102 97 | 
             
                      end
         | 
| 103 98 |  | 
| 104 99 | 
             
                      AWS::S3::Base.establish_connection!( @s3_options.merge(
         | 
| 105 | 
            -
                        :access_key_id =>  | 
| 106 | 
            -
                        :secret_access_key =>  | 
| 100 | 
            +
                        :access_key_id => s3_credentials[:access_key_id],
         | 
| 101 | 
            +
                        :secret_access_key => s3_credentials[:secret_access_key]
         | 
| 107 102 | 
             
                      ))
         | 
| 108 103 | 
             
                    end
         | 
| 109 104 | 
             
                    Paperclip.interpolates(:s3_alias_url) do |attachment, style|
         | 
| @@ -124,7 +119,23 @@ module Paperclip | |
| 124 119 | 
             
                    AWS::S3::S3Object.url_for(path(style_name), bucket_name, :expires_in => time, :use_ssl => (s3_protocol(style_name) == 'https'))
         | 
| 125 120 | 
             
                  end
         | 
| 126 121 |  | 
| 122 | 
            +
                  def s3_credentials
         | 
| 123 | 
            +
                    @s3_credentials ||= parse_credentials(@options.s3_credentials)
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  def s3_host_name
         | 
| 127 | 
            +
                    @options.s3_host_name || s3_credentials[:s3_host_name] || "s3.amazonaws.com"
         | 
| 128 | 
            +
                  end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                  def s3_host_alias
         | 
| 131 | 
            +
                    @s3_host_alias = @options.s3_host_alias
         | 
| 132 | 
            +
                    @s3_host_alias = @s3_host_alias.call(self) if @s3_host_alias.is_a?(Proc)
         | 
| 133 | 
            +
                    @s3_host_alias
         | 
| 134 | 
            +
                  end
         | 
| 135 | 
            +
             | 
| 127 136 | 
             
                  def bucket_name
         | 
| 137 | 
            +
                    @bucket = @options.bucket || s3_credentials[:bucket]
         | 
| 138 | 
            +
                    @bucket = @bucket.call(self) if @bucket.is_a?(Proc)
         | 
| 128 139 | 
             
                    @bucket
         | 
| 129 140 | 
             
                  end
         | 
| 130 141 |  | 
| @@ -148,10 +159,6 @@ module Paperclip | |
| 148 159 | 
             
                    using_http_proxy? ? @http_proxy[:password] : nil
         | 
| 149 160 | 
             
                  end
         | 
| 150 161 |  | 
| 151 | 
            -
                  def s3_host_name
         | 
| 152 | 
            -
                    @s3_host_name || "s3.amazonaws.com"
         | 
| 153 | 
            -
                  end
         | 
| 154 | 
            -
             | 
| 155 162 | 
             
                  def set_permissions permissions
         | 
| 156 163 | 
             
                    if permissions.is_a?(Hash)
         | 
| 157 164 | 
             
                      permissions[:default] = permissions[:default] || :public_read
         | 
| @@ -161,10 +168,6 @@ module Paperclip | |
| 161 168 | 
             
                    permissions
         | 
| 162 169 | 
             
                  end
         | 
| 163 170 |  | 
| 164 | 
            -
                  def s3_host_alias
         | 
| 165 | 
            -
                    @s3_host_alias
         | 
| 166 | 
            -
                  end
         | 
| 167 | 
            -
             | 
| 168 171 | 
             
                  def parse_credentials creds
         | 
| 169 172 | 
             
                    creds = find_credentials(creds).stringify_keys
         | 
| 170 173 | 
             
                    env = Object.const_defined?(:Rails) ? Rails.env : nil
         |