Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #1251 from n2uitive/rackspace_storage_metadata

Rackspace storage metadata
  • Loading branch information...
commit 043b549eed71b61cd79a4b6fe6404d4b925b53bc 2 parents 3ef5a61 + 44c5c6e
@brianhartsock brianhartsock authored
View
64 lib/fog/rackspace/models/storage/file.rb
@@ -47,6 +47,10 @@ def destroy
true
end
+ def metadata
+ @metadata ||= headers_to_metadata
+ end
+
def owner=(new_owner)
if new_owner
attributes[:owner] = {
@@ -70,8 +74,12 @@ def save(options = {})
options['Content-Type'] = content_type if content_type
options['Access-Control-Allow-Origin'] = access_control_allow_origin if access_control_allow_origin
options['Origin'] = origin if origin
- data = connection.put_object(directory.key, key, body, options)
- merge_attributes(data.headers.reject {|key, value| ['Content-Length', 'Content-Type'].include?(key)})
+ options.merge!(metadata_to_headers)
+
+ data = connection.put_object(directory.key, key, body, options)
+ update_attributes_from(data)
+ refresh_metadata
+
self.content_length = Fog::Storage.get_body_size(body)
self.content_type ||= Fog::Storage.get_content_type(body)
true
@@ -83,6 +91,58 @@ def directory=(new_directory)
@directory = new_directory
end
+ def refresh_metadata
+ metadata.reject! {|k, v| v.nil? }
+ end
+
+ def headers_to_metadata
+ key_map = key_mapping
+ Hash[metadata_attributes.map {|k, v| [key_map[k], v] }]
+ end
+
+ def key_mapping
+ key_map = metadata_attributes
+ key_map.each_pair {|k, v| key_map[k] = header_to_key(k)}
+ end
+
+ def header_to_key(opt)
+ opt.gsub(metadata_prefix, '').split('-').map {|k| k[0, 1].downcase + k[1..-1]}.join('_').to_sym
+ end
+
+ def metadata_to_headers
+ header_map = header_mapping
+ Hash[metadata.map {|k, v| [header_map[k], v] }]
+ end
+
+ def header_mapping
+ header_map = metadata.dup
+ header_map.each_pair {|k, v| header_map[k] = key_to_header(k)}
+ end
+
+ def key_to_header(key)
+ metadata_prefix + key.to_s.split(/[-_]/).map(&:capitalize).join('-')
+ end
+
+ def metadata_attributes
+ if etag
+ headers = connection.head_object(directory.key, self.key).headers
+ headers.reject! {|k, v| !metadata_attribute?(k)}
+ else
+ {}
+ end
+ end
+
+ def metadata_attribute?(key)
+ key.to_s =~ /^#{metadata_prefix}/
+ end
+
+ def metadata_prefix
+ "X-Object-Meta-"
+ end
+
+ def update_attributes_from(data)
+ merge_attributes(data.headers.reject {|key, value| ['Content-Length', 'Content-Type'].include?(key)})
+ end
end
end
View
88 tests/rackspace/models/storage/file_tests.rb
@@ -2,6 +2,16 @@
pending if Fog.mocking?
+ def object_meta_attributes
+ @instance.connection.head_object(@directory.key, @instance.key).headers.reject {|k, v| !(k =~ /X-Object-Meta-/)}
+ end
+
+ def clear_metadata
+ @instance.metadata.tap do |metadata|
+ metadata.each_pair {|k, v| metadata[k] = nil }
+ end
+ end
+
file_attributes = {
:key => 'fog_file_tests',
:body => lorem_file
@@ -18,6 +28,82 @@
model_tests(@directory.files, file_attributes, Fog.mocking?) do
+ tests("#metadata should load empty metadata").returns({}) do
+ @instance.metadata
+ end
+
+ tests('#save') do
+
+ tests('#metadata') do
+
+ before do
+ @instance.metadata[:foo] = 'bar'
+ @instance.save
+ end
+
+ after do
+ clear_metadata
+ @instance.save
+ end
+
+ tests("should update metadata").returns('bar') do
+ object_meta_attributes['X-Object-Meta-Foo']
+ end
+
+ tests('should cache metadata').returns('bar') do
+ @instance.metadata[:foo]
+ end
+
+ tests('should remove empty metadata').returns({}) do
+ @instance.metadata[:foo] = nil
+ @instance.save
+ object_meta_attributes
+ end
+
+ end
+
+ tests('#metadata keys') do
+
+ after do
+ clear_metadata
+ @instance.save
+ end
+
+ @instance.metadata[:foo_bar] = 'baz'
+ tests("should support compound key names").returns('baz') do
+ @instance.save
+ object_meta_attributes['X-Object-Meta-Foo-Bar']
+ end
+
+ @instance.metadata['foo'] = 'bar'
+ tests("should support string keys").returns('bar') do
+ @instance.save
+ object_meta_attributes['X-Object-Meta-Foo']
+ end
+
+ @instance.metadata['foo_bar'] = 'baz'
+ tests("should support compound string key names").returns('baz') do
+ @instance.save
+ object_meta_attributes['X-Object-Meta-Foo-Bar']
+ end
+
+ @instance.metadata['foo-bar'] = 'baz'
+ tests("should support hyphenated keys").returns('baz') do
+ @instance.save
+ object_meta_attributes['X-Object-Meta-Foo-Bar']
+ end
+
+ @instance.metadata['foo-bar'] = 'baz'
+ @instance.metadata[:'foo_bar'] = 'bref'
+ tests("should only support one value per metadata key").returns('bref') do
+ @instance.save
+ object_meta_attributes['X-Object-Meta-Foo-Bar']
+ end
+
+ end
+
+ end
+
tests("#access_control_allow_origin") do
tests("#access_control_allow_origin should default to nil").returns(nil) do
@@ -80,5 +166,7 @@
end
end
+
@directory.destroy
+
end
Please sign in to comment.
Something went wrong with that request. Please try again.