duracloud-client 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -3
- data/lib/duracloud/abstract_entity.rb +92 -0
- data/lib/duracloud/chunked_content.rb +35 -0
- data/lib/duracloud/client.rb +4 -4
- data/lib/duracloud/content.rb +78 -98
- data/lib/duracloud/content_manifest.rb +88 -0
- data/lib/duracloud/manifest.rb +34 -15
- data/lib/duracloud/properties.rb +1 -1
- data/lib/duracloud/request.rb +6 -5
- data/lib/duracloud/rest_methods.rb +8 -8
- data/lib/duracloud/space.rb +8 -10
- data/lib/duracloud/tsv.rb +27 -4
- data/lib/duracloud/version.rb +1 -1
- data/lib/duracloud.rb +3 -0
- data/spec/fixtures/content_manifest.xml +32 -0
- data/spec/support/shared_examples_for_tsv.rb +23 -0
- data/spec/unit/audit_log_spec.rb +5 -15
- data/spec/unit/bit_integrity_report_spec.rb +5 -15
- data/spec/unit/content_manifest_spec.rb +17 -0
- data/spec/unit/content_spec.rb +117 -28
- data/spec/unit/manifest_spec.rb +5 -14
- metadata +11 -4
- data/lib/duracloud/has_properties.rb +0 -52
- data/lib/duracloud/persistence.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 850dd8765ce4680a9a81f7453970ac9d8a33ec6d
|
4
|
+
data.tar.gz: 64f6a963ed6453f7f77af4ed9efbc93200417dfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a938f8b35fe0b32f4d6e73ac80c741adedd32c91513508f64e6cb63486299cff015cb38a394b22df2f1b56fe76024939ce06c1c3968a247406d0d069e08bd9bb
|
7
|
+
data.tar.gz: 303f6bbedfb8db0950ab9ffece57ba5989fa575dd0ed4b290004f4d13a91dfc88a252b83034bfc1503e1c81c6acfe5fe0b897da2b004ab9ab6234c86587c4128
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# duracloud-ruby-client
|
2
|
+
|
2
3
|
Ruby client for communicating with DuraCloud
|
3
4
|
|
4
5
|
## Installation
|
@@ -84,7 +85,7 @@ D, [2016-04-29T12:12:32.641574 #28275] DEBUG -- : Duracloud::Client PUT https://
|
|
84
85
|
=> #<Duracloud::Space space_id="rest-api-testing2", store_id="(default)">
|
85
86
|
```
|
86
87
|
|
87
|
-
A `Duracloud::BadRequestError` is
|
88
|
+
A `Duracloud::BadRequestError` exception is raised if the space ID is invalid (illegal characters, too long, etc.).
|
88
89
|
|
89
90
|
#### Retrieve a space and view its properties
|
90
91
|
|
@@ -100,7 +101,7 @@ D, [2016-04-29T12:15:12.593075 #28275] DEBUG -- : Duracloud::Client HEAD https:/
|
|
100
101
|
=> #<DateTime: 2016-04-05T17:59:11+00:00 ((2457484j,64751s,0n),+0s,2299161j)>
|
101
102
|
```
|
102
103
|
|
103
|
-
A `Duracloud::NotFoundError` exception is
|
104
|
+
A `Duracloud::NotFoundError` exception is raised if the space does not exist.
|
104
105
|
|
105
106
|
#### Enumerate the content IDs of the space
|
106
107
|
|
@@ -153,6 +154,12 @@ If the space or content ID does not exist, a `Duracloud::NotFoundError` is raise
|
|
153
154
|
If an MD5 digest is provided (:md5 attribute), a `Duracloud::MessageDigestError` is
|
154
155
|
raised if the content ID exists and the stored digest does not match.
|
155
156
|
|
157
|
+
*Added in v0.4.0*
|
158
|
+
|
159
|
+
If a content item is not found at the content ID, `Duracloud::Content.find` will look for a "content manifest"
|
160
|
+
by appending ".dura-manifest" to the content ID. If the manifest is found, the content item is marked as
|
161
|
+
"chunked". **Caution: Working with chunked files should be considered EXPERIMENTAL.**
|
162
|
+
|
156
163
|
#### Update the properties for a content item
|
157
164
|
|
158
165
|
```
|
@@ -177,6 +184,48 @@ D, [2016-04-29T18:32:06.465928 #32379] DEBUG -- : Duracloud::Client HEAD https:/
|
|
177
184
|
=> "bob@example.com"
|
178
185
|
```
|
179
186
|
|
187
|
+
#### Copy a content item
|
188
|
+
|
189
|
+
*Added in v0.3.0; Changed in v0.4.0.*
|
190
|
+
|
191
|
+
Accepts same keywords as `.find` and `.new` -- `:space_id`, `:content_id`, `:store_id` -- plus `:force`.
|
192
|
+
|
193
|
+
The `:force` argument is a boolean (default `false`) indicating whether to replace existing content (if found) at the target location. If `:force` is false and content exists at the target location, the operation raises a `Duracloud::Content::CopyError` exception.
|
194
|
+
|
195
|
+
Also, `:space_id` and `:content_id` arguments are not required, but default to the values of the current content object's attributes. An exception is raised if the source and destination locations are the same (regardless of the value of `:force`).
|
196
|
+
|
197
|
+
```
|
198
|
+
>> content = Duracloud::Content.find(space_id: 'rest-api-testing', content_id: 'contentItem.txt')
|
199
|
+
D, [2017-01-27T17:16:45.846459 #93283] DEBUG -- : Duracloud::Client HEAD https://duke.duracloud.org/durastore/rest-api-testing/contentItem.txt 200 OK
|
200
|
+
=> #<Duracloud::Content space_id="rest-api-testing", content_id="contentItem.txt", store_id=(default)>
|
201
|
+
|
202
|
+
>> content.copy(space_id: 'rest-api-testing2')
|
203
|
+
D, [2017-01-27T17:17:59.848741 #93283] DEBUG -- : Duracloud::Client PUT https://duke.duracloud.org/durastore/rest-api-testing2/contentItem.txt 201 Created
|
204
|
+
=> #<Duracloud::Content space_id="rest-api-testing2", content_id="contentItem.txt", store_id=(default)>
|
205
|
+
```
|
206
|
+
|
207
|
+
#### Move a content item
|
208
|
+
|
209
|
+
*Added in v0.3.0; Changed in v0.4.0.*
|
210
|
+
|
211
|
+
See also *Copy a content item, above.
|
212
|
+
|
213
|
+
```
|
214
|
+
This is a convenience operation -- copy and delete -- not directly supported by the DuraCloud REST API.
|
215
|
+
|
216
|
+
>> content = Duracloud::Content.find(space_id: 'rest-api-testing', content_id: 'contentItem.txt')
|
217
|
+
D, [2017-01-27T17:19:41.926994 #93286] DEBUG -- : Duracloud::Client HEAD https://duke.duracloud.org/durastore/rest-api-testing/contentItem.txt 200 OK
|
218
|
+
=> #<Duracloud::Content space_id="rest-api-testing", content_id="contentItem.txt", store_id=(default)>
|
219
|
+
|
220
|
+
>> content.move(space_id: 'rest-api-testing2')
|
221
|
+
D, [2017-01-27T17:20:07.542468 #93286] DEBUG -- : Duracloud::Client PUT https://duke.duracloud.org/durastore/rest-api-testing2/contentItem.txt 201 Created
|
222
|
+
D, [2017-01-27T17:20:08.442504 #93286] DEBUG -- : Duracloud::Client DELETE https://duke.duracloud.org/durastore/rest-api-testing/contentItem.txt 200 OK
|
223
|
+
=> #<Duracloud::Content space_id="rest-api-testing2", content_id="contentItem.txt", store_id=(default)>
|
224
|
+
|
225
|
+
>> content.deleted?
|
226
|
+
=> true
|
227
|
+
```
|
228
|
+
|
180
229
|
#### Delete a content item
|
181
230
|
|
182
231
|
```
|
@@ -191,7 +240,7 @@ D, [2016-04-29T18:28:31.459962 #32379] DEBUG -- : Duracloud::Client DELETE https
|
|
191
240
|
I, [2016-04-29T18:28:31.460069 #32379] INFO -- : Content foo2 deleted successfully
|
192
241
|
=> #<Duracloud::Content space_id="rest-api-testing", content_id="foo2", store_id=(default)>
|
193
242
|
|
194
|
-
>> Duracloud::Content.exist?("rest-api-testing", "foo2")
|
243
|
+
>> Duracloud::Content.exist?(space_id: "rest-api-testing", content_id: "foo2")
|
195
244
|
D, [2016-04-29T18:29:03.935451 #32379] DEBUG -- : Duracloud::Client HEAD https://foo.duracloud.org/durastore/rest-api-testing/foo2 404 Not Found
|
196
245
|
=> false
|
197
246
|
```
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
3
|
+
module Duracloud
|
4
|
+
class AbstractEntity
|
5
|
+
include ActiveModel::Model
|
6
|
+
extend ActiveModel::Callbacks
|
7
|
+
|
8
|
+
define_model_callbacks :save, :delete, :load_properties
|
9
|
+
after_save :persisted!
|
10
|
+
after_save :reset_properties
|
11
|
+
after_load_properties :persisted!
|
12
|
+
before_delete :reset_properties
|
13
|
+
after_delete :deleted!
|
14
|
+
after_delete :freeze
|
15
|
+
|
16
|
+
def save
|
17
|
+
raise Error, "Cannot save deleted #{self.class}." if deleted?
|
18
|
+
run_callbacks :save do
|
19
|
+
do_save
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete
|
24
|
+
raise Error, "Cannot delete, already deleted." if deleted?
|
25
|
+
run_callbacks :delete do
|
26
|
+
do_delete
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def persisted?
|
31
|
+
!!@persisted
|
32
|
+
end
|
33
|
+
|
34
|
+
def deleted?
|
35
|
+
!!@deleted
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the properties associated with this resource,
|
39
|
+
# loading from Duracloud if necessary.
|
40
|
+
# @return [Duracloud::Properties] the properties
|
41
|
+
# @raise [Duracloud::NotFoundError] if the resource is marked persisted
|
42
|
+
# but does not exist in Duracloud
|
43
|
+
def properties
|
44
|
+
load_properties if persisted? && @properties.nil?
|
45
|
+
@properties ||= properties_class.new
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def load_properties
|
50
|
+
run_callbacks :load_properties do
|
51
|
+
do_load_properties
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def do_load_properties
|
58
|
+
raise NotImplementedError, "Subclasses must implement `#do_load_properties` private method."
|
59
|
+
end
|
60
|
+
|
61
|
+
def persisted!
|
62
|
+
@persisted = true
|
63
|
+
end
|
64
|
+
|
65
|
+
def deleted!
|
66
|
+
@deleted = true
|
67
|
+
@persisted = false
|
68
|
+
end
|
69
|
+
|
70
|
+
def do_delete
|
71
|
+
raise NotImplementedError, "Subclasses must implement `do_delete`."
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_save
|
75
|
+
raise NotImplementedError, "Subclasses must implement `do_save`."
|
76
|
+
end
|
77
|
+
|
78
|
+
def properties=(props)
|
79
|
+
filtered = props ? properties_class.filter(props) : props
|
80
|
+
@properties = properties_class.new(filtered)
|
81
|
+
end
|
82
|
+
|
83
|
+
def reset_properties
|
84
|
+
@properties = nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def properties_class
|
88
|
+
Properties
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Duracloud
|
2
|
+
class ChunkedContent < Content
|
3
|
+
|
4
|
+
def self.find(**kwargs)
|
5
|
+
new(**kwargs).tap do |content|
|
6
|
+
content.manifest
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def manifest
|
11
|
+
if @manifest.nil?
|
12
|
+
@manifest = ContentManifest.find(space_id: space_id,
|
13
|
+
manifest_id: content_id + MANIFEST_EXT,
|
14
|
+
store_id: store_id)
|
15
|
+
load_properties
|
16
|
+
end
|
17
|
+
@manifest
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def do_load_properties
|
23
|
+
if md5
|
24
|
+
if md5 != manifest.source.md5
|
25
|
+
raise MessageDigestError, "Expected MD5: {#{md5}}; DuraCloud MD5: {#{manifest.source.md5}}."
|
26
|
+
end
|
27
|
+
else
|
28
|
+
self.md5 = manifest.source.md5
|
29
|
+
end
|
30
|
+
self.properties = manifest.properties.dup
|
31
|
+
self.content_type = manifest.source.content_type
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
data/lib/duracloud/client.rb
CHANGED
@@ -6,8 +6,8 @@ module Duracloud
|
|
6
6
|
extend RestMethods
|
7
7
|
include RestMethods
|
8
8
|
|
9
|
-
def self.execute(request_class, http_method, url, **options)
|
10
|
-
new.execute(request_class, http_method, url, **options)
|
9
|
+
def self.execute(request_class, http_method, url, **options, &block)
|
10
|
+
new.execute(request_class, http_method, url, **options, &block)
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.configure
|
@@ -22,9 +22,9 @@ module Duracloud
|
|
22
22
|
@config = Configuration.new(**options)
|
23
23
|
end
|
24
24
|
|
25
|
-
def execute(request_class, http_method, url, **options)
|
25
|
+
def execute(request_class, http_method, url, **options, &block)
|
26
26
|
request = request_class.new(self, http_method, url, **options)
|
27
|
-
response = request.execute
|
27
|
+
response = request.execute(&block)
|
28
28
|
handle_response(response)
|
29
29
|
response
|
30
30
|
end
|
data/lib/duracloud/content.rb
CHANGED
@@ -4,48 +4,57 @@ module Duracloud
|
|
4
4
|
#
|
5
5
|
# A piece of content in DuraCloud
|
6
6
|
#
|
7
|
-
class Content
|
8
|
-
include ActiveModel::Model
|
9
|
-
include ActiveModel::Dirty
|
10
|
-
include Persistence
|
11
|
-
include HasProperties
|
7
|
+
class Content < AbstractEntity
|
12
8
|
|
13
|
-
|
9
|
+
class CopyError < Error; end
|
14
10
|
|
15
|
-
|
11
|
+
CHUNK_SIZE = 1024 * 16
|
12
|
+
COPY_SOURCE_HEADER = "x-dura-meta-copy-source"
|
13
|
+
COPY_SOURCE_STORE_HEADER = "x-dura-meta-copy-source-store"
|
14
|
+
MANIFEST_EXT = ".dura-manifest"
|
16
15
|
|
17
16
|
# Does the content exist in DuraCloud?
|
18
|
-
# @return [Boolean] whether the content exists
|
19
|
-
# @raise [Duracloud::MessageDigestError] the provided digest in the :md5
|
20
|
-
# does not match the stored value
|
21
|
-
def self.exist?(
|
22
|
-
find(
|
17
|
+
# @return [Boolean] whether the content exists.
|
18
|
+
# @raise [Duracloud::MessageDigestError] the provided digest in the :md5 keyword option,
|
19
|
+
# if given, does not match the stored value.
|
20
|
+
def self.exist?(**kwargs)
|
21
|
+
find(**kwargs) && true
|
23
22
|
rescue NotFoundError
|
24
23
|
false
|
25
24
|
end
|
26
25
|
|
27
26
|
# Find content in DuraCloud.
|
28
27
|
# @return [Duraclound::Content] the content
|
29
|
-
# @raise [Duracloud::NotFoundError] the space, content, or store does not exist.
|
30
|
-
# @raise [Duracloud::MessageDigestError] the provided digest in the :md5
|
31
|
-
# does not match the stored value
|
32
|
-
def self.find(
|
33
|
-
new(
|
28
|
+
# @raise [Duracloud::NotFoundError] the space, content, or store (if given) does not exist.
|
29
|
+
# @raise [Duracloud::MessageDigestError] the provided digest in the :md5 keyword option,
|
30
|
+
# if given, does not match the stored value.
|
31
|
+
def self.find(**kwargs)
|
32
|
+
new(**kwargs).tap do |content|
|
34
33
|
content.load_properties
|
35
34
|
end
|
35
|
+
rescue NotFoundError => e
|
36
|
+
ChunkedContent.find(**kwargs)
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
+
# Create new content in DuraCloud.
|
40
|
+
# @return [Duraclound::Content] the content
|
41
|
+
# @raise [Duracloud::NotFoundError] the space or store (if given) does not exist.
|
42
|
+
# @raise [Duracloud::MessageDigestError] the provided digest in the :md5 keyword option,
|
43
|
+
# if given, does not match the stored value.
|
44
|
+
def self.create(**kwargs)
|
45
|
+
new(**kwargs).save
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_accessor :space_id, :content_id, :store_id,
|
49
|
+
:body, :md5, :content_type
|
39
50
|
alias_method :id, :content_id
|
40
51
|
validates_presence_of :space_id, :content_id
|
41
52
|
|
42
|
-
define_attribute_methods :content_type, :body, :md5
|
43
|
-
|
44
53
|
# Return the space associated with this content.
|
45
54
|
# @return [Duracloud::Space] the space.
|
46
55
|
# @raise [Duracloud::NotFoundError] the space or store does not exist.
|
47
56
|
def space
|
48
|
-
Space.find(space_id, store_id)
|
57
|
+
@space ||= Space.find(space_id, store_id)
|
49
58
|
end
|
50
59
|
|
51
60
|
def inspect
|
@@ -54,67 +63,33 @@ module Duracloud
|
|
54
63
|
" store_id=#{store_id || '(default)'}>"
|
55
64
|
end
|
56
65
|
|
57
|
-
# @api private
|
58
|
-
# @raise [Duracloud::NotFoundError] the content does not exist in DuraCloud.
|
59
|
-
def load_body
|
60
|
-
response = Client.get_content(*args, **query)
|
61
|
-
set_md5!(response)
|
62
|
-
@body = response.body # don't use setter b/c marks as dirty
|
63
|
-
persisted!
|
64
|
-
end
|
65
|
-
|
66
|
-
def load_properties
|
67
|
-
super do |response|
|
68
|
-
# don't mark content_type or md5 as changed
|
69
|
-
set_md5!(response)
|
70
|
-
@content_type = response.content_type
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def body=(str_or_io)
|
75
|
-
@body = str_or_io
|
76
|
-
body_will_change!
|
77
|
-
end
|
78
|
-
|
79
|
-
# Return the content body, loading from DuraCloud if necessary.
|
80
|
-
# @return [String, StringIO] the content body
|
81
|
-
def body
|
82
|
-
load_body if persisted? && empty?
|
83
|
-
@body
|
84
|
-
end
|
85
|
-
|
86
66
|
# Is the content empty?
|
87
67
|
# @return [Boolean] whether the content is empty (nil or empty string)
|
88
68
|
def empty?
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
def content_type=(val)
|
93
|
-
content_type_will_change! unless val == @content_type
|
94
|
-
@content_type = val
|
69
|
+
body.nil? || ( body.respond_to?(:size) && body.size == 0 )
|
95
70
|
end
|
96
71
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
def
|
102
|
-
|
103
|
-
@md5 = val
|
104
|
-
end
|
105
|
-
|
106
|
-
def md5
|
107
|
-
@md5
|
72
|
+
# Downloads the remote content
|
73
|
+
# @yield [String] chunk of the remote content, if block given.
|
74
|
+
# @return [Duracloud::Response] the response to the content request.
|
75
|
+
# @raise [Duracloud::NotFoundError]
|
76
|
+
def download(&block)
|
77
|
+
Client.get_content(*args, **query, &block)
|
108
78
|
end
|
109
79
|
|
110
80
|
# @return [Duracloud::Content] the copied content
|
111
81
|
# The current instance still represents the original content.
|
112
|
-
def copy(
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
82
|
+
def copy(**args)
|
83
|
+
dest = args.except(:force)
|
84
|
+
dest[:space_id] ||= space_id
|
85
|
+
dest[:content_id] ||= content_id
|
86
|
+
raise CopyError, "Destination is the same as the source." if dest == copy_source
|
87
|
+
if !args[:force] && Content.exist?(**dest)
|
88
|
+
raise CopyError, "Destination exists and :false option is false."
|
89
|
+
end
|
90
|
+
options = { storeID: dest[:store_id], headers: copy_headers }
|
91
|
+
Client.copy_content(dest[:space_id], dest[:content_id], **options)
|
92
|
+
Content.new(dest.merge(md5: md5))
|
118
93
|
end
|
119
94
|
|
120
95
|
# @return [Duracloud::Content] the moved content
|
@@ -127,28 +102,6 @@ module Duracloud
|
|
127
102
|
|
128
103
|
private
|
129
104
|
|
130
|
-
def set_md5!(response)
|
131
|
-
if md5
|
132
|
-
if md5 != response.md5
|
133
|
-
raise MessageDigestError,
|
134
|
-
"Expected MD5 digest (#{md5}) does not match response header: #{response.md5}"
|
135
|
-
end
|
136
|
-
else
|
137
|
-
@md5 = response.md5
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def io_like?
|
142
|
-
body.respond_to?(:read) && body.respond_to?(:rewind)
|
143
|
-
end
|
144
|
-
|
145
|
-
def set_properties
|
146
|
-
headers = properties.to_h
|
147
|
-
headers["Content-Type"] = content_type if content_type_changed?
|
148
|
-
options = { headers: headers, query: query }
|
149
|
-
Client.set_content_properties(*args, **options)
|
150
|
-
end
|
151
|
-
|
152
105
|
def store
|
153
106
|
headers = {
|
154
107
|
"Content-MD5" => md5 || calculate_md5,
|
@@ -159,6 +112,24 @@ module Duracloud
|
|
159
112
|
Client.store_content(*args, **options)
|
160
113
|
end
|
161
114
|
|
115
|
+
def copy_headers
|
116
|
+
ch = { COPY_SOURCE_HEADER=>"#{space_id}/#{content_id}" }
|
117
|
+
ch[COPY_SOURCE_STORE_HEADER] = store_id if store_id
|
118
|
+
ch
|
119
|
+
end
|
120
|
+
|
121
|
+
def copy_source
|
122
|
+
{ space_id: space_id, content_id: content_id, store_id: store_id }
|
123
|
+
end
|
124
|
+
|
125
|
+
def io_like?
|
126
|
+
body.respond_to?(:read) && body.respond_to?(:rewind)
|
127
|
+
end
|
128
|
+
|
129
|
+
def set_properties
|
130
|
+
Client.set_content_properties(*args, headers: properties, query: query)
|
131
|
+
end
|
132
|
+
|
162
133
|
def calculate_md5
|
163
134
|
digest = Digest::MD5.new
|
164
135
|
if io_like?
|
@@ -177,8 +148,17 @@ module Duracloud
|
|
177
148
|
ContentProperties
|
178
149
|
end
|
179
150
|
|
180
|
-
def
|
181
|
-
Client.get_content_properties(*args, **query)
|
151
|
+
def do_load_properties
|
152
|
+
response = Client.get_content_properties(*args, **query)
|
153
|
+
if md5
|
154
|
+
if md5 != response.md5
|
155
|
+
raise MessageDigestError, "Expected MD5: {#{md5}}; DuraCloud MD5: {#{response.md5}}."
|
156
|
+
end
|
157
|
+
else
|
158
|
+
self.md5 = response.md5
|
159
|
+
end
|
160
|
+
self.properties = response.headers
|
161
|
+
self.content_type = response.content_type
|
182
162
|
end
|
183
163
|
|
184
164
|
def do_delete
|
@@ -186,7 +166,7 @@ module Duracloud
|
|
186
166
|
end
|
187
167
|
|
188
168
|
def do_save
|
189
|
-
if !empty?
|
169
|
+
if !empty?
|
190
170
|
store
|
191
171
|
elsif persisted?
|
192
172
|
set_properties
|