def persist!(attr, options)
      unless(
        file.is_a?(ActionDispatch::Http::UploadedFile) or
        file.is_a?(Rack::Test::UploadedFile)
      )
        raise(
          "Expected #file to be a ActionDispatch::Http::UploadedFile "+
          "or Rack::Test::UploadedFile, but was #{file.inspect}"
        )
      end
      
      # Configure and save the metadata object.
      self.key = options[:key].call file # Normally, this is .default_key_proc.
      self.owner_attr = attr
      self.original_extension = ::File.extname(file.original_filename)
      self.original_basename = ::File.basename(file.original_filename, original_extension)
      self.size = file.size
      compute_mime! options
      if options[:storage].is_a? String
        self.storage_type = options[:storage]
      else
        self.storage_type = options[:storage].name
      end
      save!
    
      # Write the file to the filestore. It's possible that #file is an instance of
      # EchoUploads::MappedFile, which is a subclass of
      # ActionDispatch::Http::UploadedFile.
      if file.is_a?(ActionDispatch::Http::UploadedFile)
        storage.write key, file.tempfile, self
      else
        storage.write key, file, self
      end
      
      # If we mapped the files, they were temporarily written to tmp/echo_uploads.
      # Delete them.
      if file.is_a?(::EchoUploads::MappedFile) and ::File.exists?(file.path)
        ::File.delete file.path
      end
    
      # Prune any expired temporary files. (Unless automatic pruning was turned off in
      # the app config.)
      unless (
        Rails.configuration.echo_uploads.respond_to?(:prune_tmp_files_on_upload) and
        !Rails.configuration.echo_uploads.prune_tmp_files_on_upload
      )
        self.class.prune_temporary!
      end
    end
def persist!(attr, options)
      unless(
        file.is_a?(ActionDispatch::Http::UploadedFile) or
        file.is_a?(Rack::Test::UploadedFile)
      )
        raise(
          "Expected #file to be a ActionDispatch::Http::UploadedFile "+
          "or Rack::Test::UploadedFile, but was #{file.inspect}"
        )
      end
      
      # Configure and save the metadata object.
      self.key = options[:key].call file # Normally, this is .default_key_proc.
      self.owner_attr = attr
      self.original_extension = ::File.extname(file.original_filename)
      self.original_basename = ::File.basename(file.original_filename, original_extension)
      self.size = file.size
      compute_mime! options
      if options[:storage].is_a? String
        self.storage_type = options[:storage]
      else
        self.storage_type = options[:storage].name
      end
      save!
    
      # Write the file to the filestore. It's possible that #file is an instance of
      # EchoUploads::MappedFile, which is a subclass of
      # ActionDispatch::Http::UploadedFile.
      if file.is_a?(ActionDispatch::Http::UploadedFile)
        storage.write key, file.tempfile, self
      else
        storage.write key, file, self
      end
      
      # If we mapped the files, they were temporarily written to tmp/echo_uploads.
      # Delete them.
      if file.is_a?(::EchoUploads::MappedFile) and ::File.exists?(file.path)
        ::File.delete file.path
      end
    
      # Prune any expired temporary files. (Unless automatic pruning was turned off in
      # the app config.)
      unless (
        Rails.configuration.echo_uploads.respond_to?(:prune_tmp_files_on_upload) and
        !Rails.configuration.echo_uploads.prune_tmp_files_on_upload
      )
        self.class.prune_temporary!
      end
    end
Pass in an attribute name, an ActionDispatch::Http::UploadedFile, and an options hash.
 Must set #file attribute first.