thoughtbot/paperclip

View on GitHub
lib/paperclip/io_adapters/abstract_adapter.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'active_support/core_ext/module/delegation'

module Paperclip
  class AbstractAdapter
    OS_RESTRICTED_CHARACTERS = %r{[/:]}

    attr_reader :content_type, :original_filename, :size, :tempfile
    delegate :binmode, :binmode?, :close, :close!, :closed?, :eof?, :path, :readbyte, :rewind, :unlink, :to => :@tempfile
    alias :length :size

    def initialize(target, options = {})
      @target = target
      @options = options
    end

    def fingerprint
      @fingerprint ||= begin
        digest = @options.fetch(:hash_digest).new
        File.open(path, "rb") do |f|
          buf = ""
          digest.update(buf) while f.read(16384, buf)
        end
        digest.hexdigest
      end
    end

    def read(length = nil, buffer = nil)
      @tempfile.read(length, buffer)
    end

    def inspect
      "#{self.class}: #{self.original_filename}"
    end

    def original_filename=(new_filename)
      return unless new_filename
      @original_filename = new_filename.gsub(OS_RESTRICTED_CHARACTERS, "_")
    end

    def nil?
      false
    end

    def assignment?
      true
    end

    private

    def destination
      @destination ||= TempfileFactory.new.generate(@original_filename.to_s)
    end

    def copy_to_tempfile(src)
      link_or_copy_file(src.path, destination.path)
      destination
    end

    def link_or_copy_file(src, dest)
      begin
        Paperclip.log("Trying to link #{src} to #{dest}")
        FileUtils.ln(src, dest, force: true) # overwrite existing
      rescue Errno::EXDEV, Errno::EPERM, Errno::ENOENT, Errno::EEXIST => e
        Paperclip.log(
          "Link failed with #{e.message}; copying link #{src} to #{dest}"
        )
        FileUtils.cp(src, dest)
      end

      @destination.close
      @destination.open.binmode
    end
  end
end