module Paperclip::Storage::Aws

Public Class Methods

extended(base) click to toggle source
# File lib/paperclip-aws.rb, line 10
def self.extended base
  begin
    require 'aws-sdk'
  rescue LoadError => e
    e.message << " (You may need to install the aws-sdk gem)"
    raise e
  end unless defined?(AWS::Core)
  
  attr_accessor :s3_credentials, :s3_bucket, :s3_permissions, :s3_options, :s3_protocol, :s3_host_alias
  
  base.instance_eval do   
    self.setup_s3_credentials
    self.setup_s3_bucket                 
    self.setup_s3_permissions          
    self.setup_s3_protocol
    self.setup_s3_options
    self.setup_s3_host_alias
  end        
end

Public Instance Methods

bucket() click to toggle source
# File lib/paperclip-aws.rb, line 62
def bucket
  @bucket ||= self.s3.buckets[@s3_bucket]
end
choose_protocol(style, options={}) click to toggle source
# File lib/paperclip-aws.rb, line 94
def choose_protocol(style, options={})
  protocol = if options[:protocol].present?
    options[:protocol].to_s
  else
    @s3_protocol.is_a?(Proc) ? @s3_protocol.call(style, self) : @s3_protocol
  end

  "#{protocol}:" if protocol.present?
end
copy_to_local_file(style, local_dest_path) click to toggle source
# File lib/paperclip-aws.rb, line 154
def copy_to_local_file(style, local_dest_path)
  log("copying #{path(style)} to local file #{local_dest_path}")
  local_file = ::File.open(local_dest_path, 'wb')

  file = self.s3.buckets[@s3_bucket].objects[self.path(style)]
  local_file.write(file.read)
  local_file.close
rescue AWS::Errors::Base => e
  warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
  false
end
create_bucket() click to toggle source
# File lib/paperclip-aws.rb, line 118
def create_bucket
  self.s3.buckets.create(@s3_bucket)
end
exists?(style = default_style) click to toggle source
# File lib/paperclip-aws.rb, line 83
def exists?(style = default_style)
  if path(style).nil? || path(style).to_s.strip == ""
    return false
  end
  begin
    return self.bucket.objects[path(style)].exists?
  rescue AWS::S3::Errors::Base
    return false
  end
end
s3() click to toggle source
# File lib/paperclip-aws.rb, line 30
def s3
  @s3 ||= AWS::S3.new(
    :access_key_id => @s3_credentials[:access_key_id],
    :secret_access_key => @s3_credentials[:secret_access_key],
    :s3_endpoint => @s3_endpoint
  )        
end
s3_bucket=(value) click to toggle source
# File lib/paperclip-aws.rb, line 66
def s3_bucket=(value)
  @bucket = nil
          
  @s3_bucket = value
  @s3_bucket = @s3_bucket.call(self) if @s3_bucket.is_a?(Proc)
end
to_file(style = default_style) click to toggle source

Returns representation of the data of the file assigned to the given style, in the format most representative of the current storage.

# File lib/paperclip-aws.rb, line 106
def to_file(style = default_style)
  return @queued_for_write[style] if @queued_for_write[style]
  filename = path(style)
  extname  = File.extname(filename)
  basename = File.basename(filename, extname)
  file = Tempfile.new([basename, extname])
  file.binmode
  file.write(self.bucket.objects[path(style)].read)
  file.rewind
  return file
end
url(style=default_style, options={}) click to toggle source
Calls superclass method
# File lib/paperclip-aws.rb, line 38
def url(style=default_style, options={})
  if self.original_filename.nil? 
    # default_url = @default_url.is_a?(Proc) ? @default_url.call(self) : @default_url
    # return interpolate(default_url, style)
    return super
  end
  
  if options[:expires].present? || options[:action].present?
    options.reverse_merge!({
      :expires => 60*60,
      :action => :read
    })          
    secure = ( self.choose_protocol(style, options) == 'https:' )
    return self.s3.buckets[@s3_bucket].objects[path(style).gsub(%r{^/}, "")].url_for(options[:action], {  :secure => secure, :expires => options[:expires] }).to_s
  else
    if @s3_host_alias.present?
      url = "#{choose_protocol(style, options)}//#{@s3_host_alias}/#{path(style).gsub(%r{^/}, "")}"
    else
      url = "#{choose_protocol(style, options)}//#{@s3_endpoint}/#{@s3_bucket}/#{path(style).gsub(%r{^/}, "")}"
    end    
    return URI.escape(url)
  end              
end
versions(style = default_style) click to toggle source
# File lib/paperclip-aws.rb, line 73
def versions(style = default_style)
  begin
    return nil unless self.bucket.versioning_enabled?
    self.bucket.objects[path(style)].versions          
  rescue AWS::S3::Errors::Base => e
    log "ERROR: Error occured while fetching versions for `#{path(style)}`. Probably versions are disabled or suspended for `#{self.bucket.name}` bucket."
    return nil
  end
end

Protected Instance Methods

parse_s3_credentials(creds) click to toggle source
# File lib/paperclip-aws.rb, line 180
def parse_s3_credentials(creds)
  case creds
  when File
    YAML::load(ERB.new(File.read(creds.path)).result)
  when String, Pathname
    YAML::load(ERB.new(File.read(creds)).result)
  when Hash
    creds
  else
    raise ArgumentError, "Credentials are not a path, file, or hash."
  end
end
parse_s3_permissions(permissions) click to toggle source
# File lib/paperclip-aws.rb, line 212
def parse_s3_permissions(permissions)
  if permissions.is_a?(Hash)
    permissions[:default] = permissions[:default] || :public_read
  else
    permissions = { :default => permissions || :public_read }
  end
  permissions                
end
setup_s3_bucket() click to toggle source
# File lib/paperclip-aws.rb, line 194
def setup_s3_bucket
  if @options[:bucket].present?
    log "DEPRECATION WARNING: Passing  `:bucket` options to paperclip is deprecated. Please use `:s3_bucket` instead."
  end
  
  if @options[:s3_bucket].present? || @s3_credentials[:bucket].present? || @options[:bucket].present?
    self.s3_bucket = @options[:s3_bucket] || @s3_credentials[:bucket] || @options[:bucket]     
  else
    raise ArgumentError, "missing required :s3_bucket option"
  end
end
setup_s3_credentials() click to toggle source

PRIVATE METHODS

# File lib/paperclip-aws.rb, line 167
def setup_s3_credentials
  if @options[:s3_credentials].present?
    @s3_credentials = self.parse_s3_credentials(@options[:s3_credentials]).stringify_keys
    env = Object.const_defined?(:Rails) ? Rails.env : nil
    
    @s3_credentials = (@s3_credentials[env] || @s3_credentials).symbolize_keys              
    @s3_endpoint = @s3_credentials[:endpoint] || 's3.amazonaws.com'
  else
    raise ArgumentError, "missing required :s3_credentials option"
  end
end
setup_s3_host_alias() click to toggle source
# File lib/paperclip-aws.rb, line 246
def setup_s3_host_alias
  @s3_host_alias = @options[:s3_host_alias]
  @s3_host_alias = @s3_host_alias.call(self) if @s3_host_alias.is_a?(Proc)                            
end
setup_s3_options() click to toggle source
# File lib/paperclip-aws.rb, line 232
def setup_s3_options
  @s3_options     = (@options[:s3_options] || {}).symbolize_keys
  
  # setup Amazon Server Side encryption
  @s3_options.reverse_merge!({
    :sse => false,
    :storage_class => :standard,
    :content_disposition => nil
  })
  @s3_options[:server_side_encryption] ||= @s3_options.delete(:sse)                            
end
setup_s3_permissions() click to toggle source
# File lib/paperclip-aws.rb, line 207
def setup_s3_permissions
  @s3_permissions = self.parse_s3_permissions(@options[:s3_permissions])
end
setup_s3_protocol() click to toggle source
# File lib/paperclip-aws.rb, line 222
def setup_s3_protocol
  @s3_protocol = @options[:s3_protocol] ||
    Proc.new do |style, attachment|
      permission  = (@s3_permissions[style.to_sym] || @s3_permissions[:default])
      permission  = permission.call(attachment, style) if permission.is_a?(Proc)
      (permission == :public_read) ? 'http' : 'https'
    end                  
end