Skip to content

Commit

Permalink
Add S3Object.update for updating things like the content-type without…
Browse files Browse the repository at this point in the history
… re-uploading the file
  • Loading branch information
packagethief committed Oct 16, 2009
1 parent a27181a commit ba17303
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
28 changes: 20 additions & 8 deletions lib/aws/s3/object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,6 @@ module S3
# song.content_type = 'application/pdf'
# song.store
#
# (Keep in mind that due to limitiations in S3's exposed API, the only way to change things like the content_type
# is to PUT the object onto S3 again. In the case of large files, this will result in fully re-uploading the file.)
#
# A bevie of information about an object can be had using the <tt>about</tt> method:
#
# pp song.about
Expand Down Expand Up @@ -184,11 +181,22 @@ def copy(key, copy_key, bucket = nil, options = {})
source_key = path!(bucket, key)
default_options = {'x-amz-copy-source' => source_key}
target_key = path!(bucket, copy_key)
returning put(target_key, default_options) do
returning put(target_key, default_options.merge(options)) do
acl(copy_key, bucket, acl(key, bucket)) if options[:copy_acl]
end
end


# Updates the object with <tt>key</tt> by copying it in-place, preserving the ACL of the existing object.
# Useful for updating an object's metadata without having to re-PUT the data.
def update(key, bucket = nil, options = {})
bucket = bucket_name(bucket)
source_key = path!(bucket, key)
default_options = {'x-amz-copy-source' => source_key, 'x-amz-metadata-directive' => 'REPLACE'}
returning put(source_key, default_options.merge(options)) do
acl(key, bucket, acl(key, bucket))
end
end

# Rename the object with key <tt>from</tt> to have key in <tt>to</tt>.
def rename(from, to, bucket = nil, options = {})
copy(from, to, bucket, options)
Expand Down Expand Up @@ -538,7 +546,12 @@ def store(options = {})
end
alias_method :create, :store
alias_method :save, :store


# Updates the the current object by copying it in place.
def update
self.class.update(key, bucket.name, about.to_headers)
end

# Deletes the current object. Trying to save an object after it has been deleted with
# raise a DeletedObject exception.
def delete
Expand All @@ -547,8 +560,7 @@ def delete
self.class.delete(key, bucket.name)
end

# Copies the current object, given it the name <tt>copy_name</tt>. Keep in mind that due to limitations in
# S3's API, this operation requires retransmitting the entire object to S3.
# Copies the current object, giving it the name <tt>copy_name</tt>.
def copy(copy_name, options = {})
self.class.copy(key, copy_name, bucket.name, options)
end
Expand Down
19 changes: 18 additions & 1 deletion test/remote/object_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def test_object

response = fetch_object_at(object.url)
assert (200..299).include?(response.code.to_i)

# Copy the object

assert_nothing_raised do
Expand Down Expand Up @@ -363,6 +363,23 @@ def test_handling_a_path_that_is_not_valid_utf8
end
end

def test_updating_an_object_should_replace_its_metadata
key = 'updated-object'

S3Object.store(key, 'value does not matter', TEST_BUCKET)
object = S3Object.find(key, TEST_BUCKET)

object.content_type = 'foo/bar'
object.metadata[:foo] = 'bar'
object.update

reloaded_object = S3Object.find(key, TEST_BUCKET)
assert_equal 'foo/bar', reloaded_object.content_type
assert_equal 'bar', reloaded_object.metadata[:foo]
ensure
S3Object.delete(key, TEST_BUCKET)
end

private
def fetch_object_at(url)
Net::HTTP.get_response(URI.parse(url))
Expand Down

0 comments on commit ba17303

Please sign in to comment.