module Defog
# Create a Defog::File proxy instance via Defog::Proxy#file, such as
#
# defog = Defog::Proxy.new(:provider => :AWS, :aws_access_key_id => access_key, ...)
#
# defog.file("key/to/my/file", "w") do |file|
# # ... access the proxy file ...
# end
#
# or
#
# file = defog.file("key/to/my/file", "w")
# # ... access the proxy file ...
# file.close
#
# Defog::File inherits from ::File, so you can act on the proxy file using
# ordinary IO methods, such as
#
# defog.file("key", "r") do |file|
# file.readlines
# end
#
# You can also access the proxy file via its path, allowing things such
# as
# defog.file("image100x100.jpg", "w") do |file|
# system("convert souce.png -scale 100x100 #{file.path}")
# end
#
# (Note that the proxy file path has the same file extension as the cloud key string.)
#
# Upon closing the proxy file, in normal use the cloud storage gets synchronized and
# the proxy deleted. See File#close for more details.
class File < ::File
def self.get(opts={}, &block) #:nodoc:
opts = opts.keyword_args(:proxy => :required, :key => :required, :mode => :required, :persist => :optional)
proxy_path = opts[:proxy_path] = Pathname.new("#{opts.proxy.proxy_root}/#{opts.key}").expand_path
proxy_path.dirname.mkpath
case opts.mode
when "r" then
opts.proxy.fog_wrapper.get_file(opts.key, proxy_path)
when "w", "w+" then
opts[:upload] = true
when "r+", "a", "a+" then
opts.proxy.fog_wrapper.get_file(opts.key, proxy_path)
opts[:upload] = true
else
raise ArgumentError, "Invalid mode #{opts.mode.inspect}"
end
self.open(opts, &block)
end
def initialize(opts={}, &block) #:nodoc:
@defog = opts.keyword_args(:proxy => :required, :mode => :required, :key => :required, :proxy_path => :required, :upload => :optional, :persist => :optional)
super(@defog.proxy_path, @defog.mode, &block)
end
# Closes the proxy file and, in the common case, synchronizes the cloud storage
# then deletes the proxy file.
#
# Synchronization can be suppressed by passing the option
# :synchronize => false
# Synchronization will also be implicitly suppressed if the proxy file
# was deleted before this call, e.g., via ::File.unlink(file.path)
.
#
#
# Whether the proxy file gets deleted vs persisted after the close can
# be set by passing the option
# :persist => true or false
# (This will override the setting of :persist
passed to Proxy#file)
#
def close(opts={})
opts = opts.keyword_args(:persist => @defog.persist, :synchronize => true)
super()
if @defog.proxy_path.exist?
@defog.proxy.fog_wrapper.put_file(@defog.key, @defog.proxy_path) if @defog.upload and opts.synchronize
@defog.proxy_path.unlink unless opts.persist
end
end
end
end