rubydora 0.5.10 → 0.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.textile +20 -0
- data/VERSION +1 -1
- data/lib/rubydora/digital_object.rb +21 -5
- data/lib/rubydora/rest_api_client.rb +135 -173
- data/lib/rubydora/transactions.rb +159 -0
- data/lib/rubydora.rb +2 -0
- data/rubydora.gemspec +2 -0
- data/spec/lib/integration_test_spec.rb +112 -0
- data/spec/lib/rest_api_client_spec.rb +39 -2
- data/spec/lib/transactions_spec.rb +126 -0
- data/spec/spec_helper.rb +1 -0
- metadata +37 -2
data/History.textile
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
h3. 0.5.11
|
2
|
+
* Ensure that the base rest resource is insulated from blocks passed to dissemination and datastream_dissemination.
|
3
|
+
* Deprecated a behavior for DigitalObject.find that allowed one to call DigitalObject.find for a non-existent object. This will raise an exception in a future rubydora release. Instead, you should use the new DigitalObject.find_or_initialize for that behavior.
|
4
|
+
* Use ActiveSupport::Rescuable for the REST API calls.
|
5
|
+
* Implement a basic form of "transactions" in Rubydora, intended to be used during testing. It uses the new REST API hooks and knows how to roll-back the different data-changing operations. In some cases, this involves deleting and re-ingesting the previous version of the object (purge, modify datastream, purge datastream), which make it unsuitable for production use, especially with large content datastreams.
|
6
|
+
|
7
|
+
At Stanford, we've hooked it into our rspec tests as an around filter:
|
8
|
+
bc. RSpec.configure do |config|
|
9
|
+
…
|
10
|
+
config.around(:each) do |example|
|
11
|
+
ActiveFedora::Base.connection_for_pid(0).transaction do |t|
|
12
|
+
example.call
|
13
|
+
t.rollback
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
h3. 0.5.10
|
19
|
+
* Support for content_changed? and content_will_change!
|
20
|
+
|
1
21
|
h3. 0.5.9
|
2
22
|
* Raise exception if it's not 404
|
3
23
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.11
|
@@ -16,6 +16,10 @@ module Rubydora
|
|
16
16
|
include Rubydora::ModelsMixin
|
17
17
|
include Rubydora::RelationshipsMixin
|
18
18
|
|
19
|
+
extend Deprecation
|
20
|
+
|
21
|
+
self.deprecation_horizon = 'rubydora 0.6'
|
22
|
+
|
19
23
|
|
20
24
|
attr_reader :pid
|
21
25
|
|
@@ -44,7 +48,23 @@ module Rubydora
|
|
44
48
|
# @param [String] pid
|
45
49
|
# @param [Rubydora::Repository] context
|
46
50
|
def self.find pid, repository = nil, options = {}
|
47
|
-
self.new pid, repository, options
|
51
|
+
obj = self.new pid, repository, options
|
52
|
+
if obj.new?
|
53
|
+
Deprecation.warn(Rubydora::DigitalObject, "DigitalObject.find called
|
54
|
+
for an object that doesn't exist. In #{Rubydora::DigitalObject.deprecation_horizon},
|
55
|
+
this behavior will raise an exception. Use
|
56
|
+
DigitalObject.new or DigitalObject.find_or_initialize instead.")
|
57
|
+
end
|
58
|
+
|
59
|
+
obj
|
60
|
+
end
|
61
|
+
|
62
|
+
# find or initialize a Fedora object
|
63
|
+
# @param [String] pid
|
64
|
+
# @param [Rubydora::Repository] repository context
|
65
|
+
# @param [Hash] options default attribute values (used esp. for creating new datastreams
|
66
|
+
def self.find_or_initialize *args
|
67
|
+
self.new *args
|
48
68
|
end
|
49
69
|
|
50
70
|
# create a new fedora object (see also DigitalObject#save)
|
@@ -258,10 +278,6 @@ module Rubydora
|
|
258
278
|
raise "Can't change values on older versions" if @asOfDateTime
|
259
279
|
end
|
260
280
|
|
261
|
-
def check_if_read_only
|
262
|
-
raise "Can't change values on older versions" if @asOfDateTime
|
263
|
-
end
|
264
|
-
|
265
281
|
private
|
266
282
|
def attribute_will_change! *args
|
267
283
|
check_if_read_only
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
require 'active_support/core_ext/class'
|
3
|
+
require 'active_support/core_ext/module'
|
4
|
+
require 'hooks'
|
2
5
|
|
3
6
|
module Rubydora
|
4
7
|
|
@@ -6,17 +9,42 @@ module Rubydora
|
|
6
9
|
module RestApiClient
|
7
10
|
|
8
11
|
include Rubydora::FedoraUrlHelpers
|
12
|
+
extend ActiveSupport::Concern
|
9
13
|
include ActiveSupport::Benchmarkable
|
10
14
|
|
15
|
+
|
11
16
|
VALID_CLIENT_OPTIONS = [:user, :password, :timeout, :open_timeout, :ssl_client_cert, :ssl_client_key]
|
17
|
+
|
18
|
+
included do
|
19
|
+
include ActiveSupport::Rescuable
|
20
|
+
|
21
|
+
|
22
|
+
rescue_from RestClient::InternalServerError do |e|
|
23
|
+
logger.error e.response
|
24
|
+
logger.flush if logger.respond_to? :flush
|
25
|
+
raise FedoraInvalidRequest, "See logger for details"
|
26
|
+
end
|
27
|
+
|
28
|
+
rescue_from Errno::ECONNREFUSED, Errno::EHOSTUNREACH do |exception|
|
29
|
+
logger.error "Unable to connect to Fedora at #{@client.url}"
|
30
|
+
raise exception
|
31
|
+
end
|
32
|
+
|
33
|
+
include Hooks
|
34
|
+
[:ingest, :modify_object, :purge_object, :set_datastream_options, :add_datastream, :modify_datastream, :purge_datastream, :add_relationship, :purge_relationship].each do |h|
|
35
|
+
define_hook "before_#{h}"
|
36
|
+
end
|
37
|
+
|
38
|
+
define_hook "after_ingest"
|
39
|
+
include Transactions
|
40
|
+
end
|
41
|
+
|
12
42
|
# Create an authorized HTTP client for the Fedora REST API
|
13
43
|
# @param [Hash] config
|
14
44
|
# @option config [String] :url
|
15
45
|
# @option config [String] :user
|
16
46
|
# @option config [String] :password
|
17
47
|
# @return [RestClient::Resource]
|
18
|
-
|
19
|
-
|
20
48
|
#TODO trap for these errors specifically: RestClient::Request::Unauthorized, Errno::ECONNREFUSED
|
21
49
|
def client config = {}
|
22
50
|
client_config = self.config.merge(config)
|
@@ -37,13 +65,9 @@ module Rubydora
|
|
37
65
|
# @return [String]
|
38
66
|
def next_pid options = {}
|
39
67
|
options[:format] ||= 'xml'
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
logger.error e.response
|
44
|
-
logger.flush if logger.respond_to? :flush
|
45
|
-
raise FedoraInvalidRequest, "Error getting nextPID. See logger for details"
|
46
|
-
end
|
68
|
+
client[next_pid_url(options)].post nil
|
69
|
+
rescue Exception => exception
|
70
|
+
rescue_with_handler(exception) || raise
|
47
71
|
end
|
48
72
|
|
49
73
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -53,17 +77,13 @@ module Rubydora
|
|
53
77
|
raise ArgumentError,"Cannot have both :terms and :query parameters" if options[:terms] and options[:query]
|
54
78
|
options[:resultFormat] ||= 'xml'
|
55
79
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
logger.error e.response
|
64
|
-
logger.flush if logger.respond_to? :flush
|
65
|
-
raise FedoraInvalidRequest, "Error finding objects. See logger for details"
|
66
|
-
end
|
80
|
+
resource = client[find_objects_url(options)]
|
81
|
+
if block_given?
|
82
|
+
resource.options[:block_response] = block_response
|
83
|
+
end
|
84
|
+
return resource.get
|
85
|
+
rescue Exception => exception
|
86
|
+
rescue_with_handler(exception) || raise
|
67
87
|
end
|
68
88
|
|
69
89
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -73,15 +93,9 @@ module Rubydora
|
|
73
93
|
def object options = {}
|
74
94
|
pid = options.delete(:pid)
|
75
95
|
options[:format] ||= 'xml'
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
raise e
|
80
|
-
rescue RestClient::InternalServerError => e
|
81
|
-
logger.error e.response
|
82
|
-
logger.flush if logger.respond_to? :flush
|
83
|
-
raise FedoraInvalidRequest, "Error getting object #{pid}. See logger for details"
|
84
|
-
end
|
96
|
+
client[object_url(pid, options)].get
|
97
|
+
rescue Exception => exception
|
98
|
+
rescue_with_handler(exception) || raise
|
85
99
|
end
|
86
100
|
|
87
101
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -91,16 +105,11 @@ module Rubydora
|
|
91
105
|
def ingest options = {}
|
92
106
|
pid = options.delete(:pid) || 'new'
|
93
107
|
file = options.delete(:file)
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
raise
|
99
|
-
rescue RestClient::InternalServerError => e
|
100
|
-
logger.error e.response
|
101
|
-
logger.flush if logger.respond_to? :flush
|
102
|
-
raise FedoraInvalidRequest, "Error ingesting object #{pid}. See logger for details"
|
103
|
-
end
|
108
|
+
assigned_pid = client[object_url(pid, options)].post file, :content_type => 'text/xml'
|
109
|
+
run_hook :after_ingest, :pid => assigned_pid, :file => file, :options => options
|
110
|
+
assigned_pid
|
111
|
+
rescue Exception => exception
|
112
|
+
rescue_with_handler(exception) || raise
|
104
113
|
end
|
105
114
|
|
106
115
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -109,12 +118,9 @@ module Rubydora
|
|
109
118
|
# @return [String]
|
110
119
|
def export options = {}
|
111
120
|
pid = options.delete(:pid)
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
logger.error e.response
|
116
|
-
raise FedoraInvalidRequest, "Error exporting object #{pid}. See logger for details"
|
117
|
-
end
|
121
|
+
client[export_object_url(pid, options)].get
|
122
|
+
rescue Exception => exception
|
123
|
+
rescue_with_handler(exception) || raise
|
118
124
|
end
|
119
125
|
|
120
126
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -123,13 +129,10 @@ module Rubydora
|
|
123
129
|
# @return [String]
|
124
130
|
def modify_object options = {}
|
125
131
|
pid = options.delete(:pid)
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
logger.flush if logger.respond_to? :flush
|
131
|
-
raise FedoraInvalidRequest, "Error modifying object #{pid}. See logger for details"
|
132
|
-
end
|
132
|
+
run_hook :before_modify_object, :pid => pid, :options => options
|
133
|
+
client[object_url(pid, options)].put nil
|
134
|
+
rescue Exception => exception
|
135
|
+
rescue_with_handler(exception) || raise
|
133
136
|
end
|
134
137
|
|
135
138
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -138,15 +141,10 @@ module Rubydora
|
|
138
141
|
# @return [String]
|
139
142
|
def purge_object options = {}
|
140
143
|
pid = options.delete(:pid)
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
raise
|
145
|
-
rescue RestClient::InternalServerError => e
|
146
|
-
logger.error e.response
|
147
|
-
logger.flush if logger.respond_to? :flush
|
148
|
-
raise FedoraInvalidRequest, "Error purging object #{pid}. See logger for details"
|
149
|
-
end
|
144
|
+
run_hook :before_purge_object, :pid => pid, :options => options
|
145
|
+
client[object_url(pid, options)].delete
|
146
|
+
rescue Exception => exception
|
147
|
+
rescue_with_handler(exception) || raise
|
150
148
|
end
|
151
149
|
|
152
150
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -157,13 +155,9 @@ module Rubydora
|
|
157
155
|
pid = options.delete(:pid)
|
158
156
|
options[:format] ||= 'xml'
|
159
157
|
raise ArgumentError, "Must have a pid" unless pid
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
logger.error e.response
|
164
|
-
logger.flush if logger.respond_to? :flush
|
165
|
-
raise FedoraInvalidRequest, "Error getting versions for object #{pid}. See logger for details"
|
166
|
-
end
|
158
|
+
client[object_versions_url(pid, options)].get
|
159
|
+
rescue Exception => exception
|
160
|
+
rescue_with_handler(exception) || raise
|
167
161
|
end
|
168
162
|
|
169
163
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -174,13 +168,9 @@ module Rubydora
|
|
174
168
|
pid = options.delete(:pid)
|
175
169
|
raise ArgumentError, "Missing required parameter :pid" unless pid
|
176
170
|
options[:format] ||= 'xml'
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
logger.error e.response
|
181
|
-
logger.flush if logger.respond_to? :flush
|
182
|
-
raise FedoraInvalidRequest, "Error getting objectXML for object #{pid}. See logger for details"
|
183
|
-
end
|
171
|
+
client[object_xml_url(pid, options)].get
|
172
|
+
rescue Exception => exception
|
173
|
+
rescue_with_handler(exception) || raise
|
184
174
|
end
|
185
175
|
|
186
176
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -194,26 +184,18 @@ module Rubydora
|
|
194
184
|
pid = options.delete(:pid)
|
195
185
|
dsid = options.delete(:dsid)
|
196
186
|
options[:format] ||= 'xml'
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
val = client[datastream_url(pid, dsid, options)].get
|
202
|
-
end
|
203
|
-
return val
|
204
|
-
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH => e
|
205
|
-
logger.error "Unable to connect to Fedora at #{@client.url}"
|
206
|
-
raise e
|
207
|
-
rescue RestClient::ResourceNotFound => e
|
208
|
-
raise e
|
209
|
-
rescue RestClient::Unauthorized => e
|
210
|
-
logger.error "Unauthorized at #{client.url}/#{datastream_url(pid, dsid, options)}"
|
211
|
-
raise e
|
212
|
-
rescue RestClient::InternalServerError => e
|
213
|
-
logger.error e.response
|
214
|
-
logger.flush if logger.respond_to? :flush
|
215
|
-
raise FedoraInvalidRequest, "Error getting datastream '#{dsid}' for object #{pid}. See logger for details"
|
187
|
+
val = nil
|
188
|
+
message = dsid.nil? ? "Loaded datastream list for #{pid}" : "Loaded datastream #{pid}/#{dsid}"
|
189
|
+
benchmark message, :level=>:debug do
|
190
|
+
val = client[datastream_url(pid, dsid, options)].get
|
216
191
|
end
|
192
|
+
|
193
|
+
val
|
194
|
+
rescue RestClient::Unauthorized => e
|
195
|
+
logger.error "Unauthorized at #{client.url}/#{datastream_url(pid, dsid, options)}"
|
196
|
+
raise e
|
197
|
+
rescue Exception => exception
|
198
|
+
rescue_with_handler(exception) || raise
|
217
199
|
end
|
218
200
|
|
219
201
|
alias_method :datastreams, :datastream
|
@@ -226,13 +208,10 @@ module Rubydora
|
|
226
208
|
def set_datastream_options options = {}
|
227
209
|
pid = options.delete(:pid)
|
228
210
|
dsid = options.delete(:dsid)
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
logger.flush if logger.respond_to? :flush
|
234
|
-
raise FedoraInvalidRequest, "Error setting datastream options on #{dsid} for object #{pid}. See logger for details"
|
235
|
-
end
|
211
|
+
run_hook :before_set_datastream_options, :pid => pid, :dsid => dsid, :options => options
|
212
|
+
client[datastream_url(pid, dsid, options)].put nil
|
213
|
+
rescue Exception => exception
|
214
|
+
rescue_with_handler(exception) || raise
|
236
215
|
end
|
237
216
|
|
238
217
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -245,16 +224,12 @@ module Rubydora
|
|
245
224
|
dsid = options.delete(:dsid)
|
246
225
|
raise ArgumentError, "Must supply dsid" unless dsid
|
247
226
|
options[:format] ||= 'xml'
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
logger.error e.response
|
255
|
-
logger.flush if logger.respond_to? :flush
|
256
|
-
raise FedoraInvalidRequest, "Error getting versions for datastream #{dsid} for object #{pid}. See logger for details"
|
257
|
-
end
|
227
|
+
client[datastream_history_url(pid, dsid, options)].get
|
228
|
+
rescue RestClient::ResourceNotFound => e
|
229
|
+
#404 Resource Not Found: No datastream history could be found. There is no datastream history for the digital object "changeme:1" with datastream ID of "descMetadata
|
230
|
+
return nil
|
231
|
+
rescue Exception => exception
|
232
|
+
rescue_with_handler(exception) || raise
|
258
233
|
end
|
259
234
|
|
260
235
|
alias_method :datastream_history, :datastream_versions
|
@@ -270,19 +245,14 @@ module Rubydora
|
|
270
245
|
method = options.delete(:method)
|
271
246
|
method ||= :get
|
272
247
|
raise self.class.name + "#datastream_dissemination requires a DSID" unless dsid
|
273
|
-
|
248
|
+
if block_given?
|
249
|
+
resource = safe_subresource(datastream_content_url(pid, dsid, options), :block_response => block_response)
|
250
|
+
else
|
274
251
|
resource = client[datastream_content_url(pid, dsid, options)]
|
275
|
-
if block_given?
|
276
|
-
resource.options[:block_response] = block_response
|
277
|
-
end
|
278
|
-
return resource.send(method)
|
279
|
-
rescue RestClient::ResourceNotFound => e
|
280
|
-
raise e
|
281
|
-
rescue RestClient::InternalServerError => e
|
282
|
-
logger.error e.response
|
283
|
-
logger.flush if logger.respond_to? :flush
|
284
|
-
raise FedoraInvalidRequest, "Error getting dissemination for datastream #{dsid} for object #{pid}. See logger for details"
|
285
252
|
end
|
253
|
+
resource.send(method)
|
254
|
+
rescue Exception => exception
|
255
|
+
rescue_with_handler(exception) || raise
|
286
256
|
end
|
287
257
|
|
288
258
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -295,13 +265,10 @@ module Rubydora
|
|
295
265
|
dsid = options.delete(:dsid)
|
296
266
|
file = options.delete(:content)
|
297
267
|
content_type = options.delete(:content_type) || options[:mimeType] || (MIME::Types.type_for(file.path).first if file.respond_to? :path) || 'application/octet-stream'
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
logger.flush if logger.respond_to? :flush
|
303
|
-
raise FedoraInvalidRequest, "Error adding datastream #{dsid} for object #{pid}. See logger for details"
|
304
|
-
end
|
268
|
+
run_hook :before_add_datastream, :pid => pid, :dsid => dsid, :file => file, :options => options
|
269
|
+
client[datastream_url(pid, dsid, options)].post file, :content_type => content_type.to_s, :multipart => true
|
270
|
+
rescue Exception => exception
|
271
|
+
rescue_with_handler(exception) || raise
|
305
272
|
end
|
306
273
|
|
307
274
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -321,13 +288,11 @@ module Rubydora
|
|
321
288
|
rest_client_options[:content_type] = content_type
|
322
289
|
end
|
323
290
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
raise FedoraInvalidRequest, "Error modifying datastream #{dsid} for #{pid}. See logger for details"
|
330
|
-
end
|
291
|
+
run_hook :before_modify_datastream, :pid => pid, :dsid => dsid, :file => file, :content_type => content_type, :options => options
|
292
|
+
client[datastream_url(pid, dsid, options)].put(file, rest_client_options)
|
293
|
+
|
294
|
+
rescue Exception => exception
|
295
|
+
rescue_with_handler(exception) || raise
|
331
296
|
end
|
332
297
|
|
333
298
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -338,13 +303,10 @@ module Rubydora
|
|
338
303
|
def purge_datastream options = {}
|
339
304
|
pid = options.delete(:pid)
|
340
305
|
dsid = options.delete(:dsid)
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
logger.flush if logger.respond_to? :flush
|
346
|
-
raise FedoraInvalidRequest, "Error purging datastream #{dsid} for #{pid}. See logger for details"
|
347
|
-
end
|
306
|
+
run_hook :before_purge_datastream, :pid => pid, :dsid => dsid
|
307
|
+
client[datastream_url(pid, dsid, options)].delete
|
308
|
+
rescue Exception => exception
|
309
|
+
rescue_with_handler(exception) || raise
|
348
310
|
end
|
349
311
|
|
350
312
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -355,13 +317,9 @@ module Rubydora
|
|
355
317
|
pid = options.delete(:pid) || options[:subject]
|
356
318
|
raise ArgumentError, "Missing required parameter :pid" unless pid
|
357
319
|
options[:format] ||= 'xml'
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
logger.error e.response
|
362
|
-
logger.flush if logger.respond_to? :flush
|
363
|
-
raise FedoraInvalidRequest, "Error getting relationships for #{pid}. See logger for details"
|
364
|
-
end
|
320
|
+
client[object_relationship_url(pid, options)].get
|
321
|
+
rescue Exception => exception
|
322
|
+
rescue_with_handler(exception) || raise
|
365
323
|
end
|
366
324
|
|
367
325
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -370,13 +328,10 @@ module Rubydora
|
|
370
328
|
# @return [String]
|
371
329
|
def add_relationship options = {}
|
372
330
|
pid = options.delete(:pid) || options[:subject]
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
logger.flush if logger.respond_to? :flush
|
378
|
-
raise FedoraInvalidRequest, "Error adding relationship for #{pid}. See logger for details"
|
379
|
-
end
|
331
|
+
run_hook :before_add_relationship, :pid => pid, :options => options
|
332
|
+
client[new_object_relationship_url(pid, options)].post nil
|
333
|
+
rescue Exception => exception
|
334
|
+
rescue_with_handler(exception) || raise
|
380
335
|
end
|
381
336
|
|
382
337
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -385,13 +340,10 @@ module Rubydora
|
|
385
340
|
# @return [String]
|
386
341
|
def purge_relationship options = {}
|
387
342
|
pid = options.delete(:pid) || options[:subject]
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
logger.flush if logger.respond_to? :flush
|
393
|
-
raise FedoraInvalidRequest, "Error purging relationships for #{pid}. See logger for details"
|
394
|
-
end
|
343
|
+
run_hook :before_purge_relationship, :pid => pid, :options => options
|
344
|
+
client[object_relationship_url(pid, options)].delete
|
345
|
+
rescue Exception => exception
|
346
|
+
rescue_with_handler(exception) || raise
|
395
347
|
end
|
396
348
|
|
397
349
|
# {include:RestApiClient::API_DOCUMENTATION}
|
@@ -405,16 +357,26 @@ module Rubydora
|
|
405
357
|
sdef = options.delete(:sdef)
|
406
358
|
method = options.delete(:method)
|
407
359
|
options[:format] ||= 'xml' unless pid and sdef and method
|
408
|
-
|
360
|
+
if block_given?
|
361
|
+
resource = safe_subresource(dissemination_url(pid,sdef,method,options), :block_response => block_response)
|
362
|
+
else
|
409
363
|
resource = client[dissemination_url(pid,sdef,method,options)]
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
364
|
+
end
|
365
|
+
resource.get
|
366
|
+
|
367
|
+
rescue Exception => exception
|
368
|
+
rescue_with_handler(exception) || raise
|
369
|
+
|
370
|
+
end
|
371
|
+
|
372
|
+
def safe_subresource(subresource, options=Hash.new)
|
373
|
+
url = client.concat_urls(client.url, subresource)
|
374
|
+
options = client.options.dup.merge! options
|
375
|
+
block = client.block
|
376
|
+
if block
|
377
|
+
client.class.new(url, options, &block)
|
378
|
+
else
|
379
|
+
client.class.new(url, options)
|
418
380
|
end
|
419
381
|
end
|
420
382
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Rubydora
|
2
|
+
# Extremely basic (and naive) 'transaction' support for Rubydora. This isn't
|
3
|
+
# really intended to be used in a production-like situation -- more for
|
4
|
+
# rolling back (small) changes during testing.
|
5
|
+
module Transactions
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :use_transactions
|
10
|
+
end
|
11
|
+
|
12
|
+
included do
|
13
|
+
after_ingest do |options|
|
14
|
+
append_to_transactions_log :ingest, options if Rubydora::Transactions.use_transactions
|
15
|
+
end
|
16
|
+
|
17
|
+
before_purge_object do |options|
|
18
|
+
append_to_transactions_log :purge_object, :pid => options[:pid], :foxml => export(:pid => options[:pid], :context => :archive) if Rubydora::Transactions.use_transactions
|
19
|
+
end
|
20
|
+
|
21
|
+
before_modify_datastream do |options|
|
22
|
+
append_to_transactions_log :modify_datastream, :pid => options[:pid], :foxml => export(:pid => options[:pid], :context => :archive) if Rubydora::Transactions.use_transactions
|
23
|
+
end
|
24
|
+
|
25
|
+
before_purge_datastream do |options|
|
26
|
+
append_to_transactions_log :purge_datastream, :pid => options[:pid], :foxml => export(:pid => options[:pid], :context => :archive) if Rubydora::Transactions.use_transactions
|
27
|
+
end
|
28
|
+
|
29
|
+
before_add_datastream do |options|
|
30
|
+
append_to_transactions_log :add_datastream, options if Rubydora::Transactions.use_transactions
|
31
|
+
end
|
32
|
+
|
33
|
+
before_add_relationship do |options|
|
34
|
+
append_to_transactions_log :add_relationship, options if Rubydora::Transactions.use_transactions
|
35
|
+
end
|
36
|
+
|
37
|
+
before_purge_relationship do |options|
|
38
|
+
append_to_transactions_log :purge_relationship, options if Rubydora::Transactions.use_transactions
|
39
|
+
end
|
40
|
+
|
41
|
+
before_modify_object do |options|
|
42
|
+
if Rubydora::Transactions.use_transactions
|
43
|
+
obj = find(options[:pid])
|
44
|
+
append_to_transactions_log :modify_object, :pid => options[:pid], :state => obj.state, :ownerId => obj.ownerId, :logMessage => 'reverting'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before_set_datastream_options do |options|
|
49
|
+
if Rubydora::Transactions.use_transactions
|
50
|
+
obj = find(options[:pid])
|
51
|
+
ds = obj.datastreams[options[:dsid]]
|
52
|
+
|
53
|
+
if options[:options][:versionable]
|
54
|
+
append_to_transactions_log :set_datastream_options, :pid => options[:pid], :dsid => options[:dsid], :versionable => ds.versionable
|
55
|
+
end
|
56
|
+
|
57
|
+
if options[:options][:state]
|
58
|
+
append_to_transactions_log :set_datastream_options, :pid => options[:pid], :dsid => options[:dsid], :state => ds.state
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
# Start a transaction
|
67
|
+
def transaction &block
|
68
|
+
Transaction.new self, &block
|
69
|
+
self.transactions_log.clear
|
70
|
+
end
|
71
|
+
|
72
|
+
# Unshift a transaction entry onto the transaction logs.
|
73
|
+
# We want these entries in reverse-chronological order
|
74
|
+
# for ease of undoing..
|
75
|
+
def append_to_transactions_log *args
|
76
|
+
return unless Rubydora::Transactions.use_transactions
|
77
|
+
transactions_log.unshift(args)
|
78
|
+
end
|
79
|
+
|
80
|
+
# The repository transaction log.
|
81
|
+
def transactions_log
|
82
|
+
@log ||= []
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Transaction
|
87
|
+
attr_reader :repository
|
88
|
+
def initialize repository, &block
|
89
|
+
@repository = repository
|
90
|
+
with_transactions(&block)
|
91
|
+
end
|
92
|
+
|
93
|
+
def with_transactions &block
|
94
|
+
old_state = Rubydora::Transactions.use_transactions
|
95
|
+
Rubydora::Transactions.use_transactions = true
|
96
|
+
|
97
|
+
yield(self)
|
98
|
+
|
99
|
+
Rubydora::Transactions.use_transactions = old_state
|
100
|
+
end
|
101
|
+
|
102
|
+
def without_transactions &block
|
103
|
+
old_state = Rubydora::Transactions.use_transactions
|
104
|
+
Rubydora::Transactions.use_transactions = false
|
105
|
+
|
106
|
+
yield(self)
|
107
|
+
|
108
|
+
Rubydora::Transactions.use_transactions = old_state
|
109
|
+
end
|
110
|
+
|
111
|
+
# Roll-back transactions by reversing their outcomes
|
112
|
+
# (or, in some cases, re-ingesting the object at the
|
113
|
+
# previous state.
|
114
|
+
def rollback
|
115
|
+
without_transactions do
|
116
|
+
repository.transactions_log.delete_if do |(method, options)|
|
117
|
+
|
118
|
+
begin
|
119
|
+
case method
|
120
|
+
when :ingest
|
121
|
+
repository.purge_object :pid => options[:pid]
|
122
|
+
|
123
|
+
when :modify_object
|
124
|
+
repository.modify_object options
|
125
|
+
|
126
|
+
when :add_datastream
|
127
|
+
repository.purge_datastream :pid => options[:pid], :dsid => options[:dsid]
|
128
|
+
|
129
|
+
when :add_relationship
|
130
|
+
repository.purge_relationship options[:options].merge(:pid => options[:pid])
|
131
|
+
|
132
|
+
when :purge_relationship
|
133
|
+
repository.add_relationship options[:options].merge(:pid => options[:pid])
|
134
|
+
|
135
|
+
when :purge_object
|
136
|
+
repository.ingest :pid => options[:pid], :file => options[:foxml]
|
137
|
+
|
138
|
+
when :set_datastream_options
|
139
|
+
repository.set_datastream_options options
|
140
|
+
|
141
|
+
when :modify_datastream
|
142
|
+
repository.purge_object :pid => options[:pid] rescue nil
|
143
|
+
repository.ingest :pid => options[:pid], :file => options[:foxml]
|
144
|
+
|
145
|
+
when :purge_datastream
|
146
|
+
repository.purge_object :pid => options[:pid] rescue nil
|
147
|
+
repository.ingest :pid => options[:pid], :file => options[:foxml]
|
148
|
+
end
|
149
|
+
rescue
|
150
|
+
# no-op
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
155
|
+
true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
data/lib/rubydora.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# Fedora Commons REST API module
|
2
2
|
require 'active_model'
|
3
|
+
require 'deprecation'
|
3
4
|
|
4
5
|
module Rubydora
|
5
6
|
autoload :Datastream, "rubydora/datastream"
|
@@ -15,6 +16,7 @@ module Rubydora
|
|
15
16
|
autoload :ExtensionParameters, "rubydora/extension_parameters"
|
16
17
|
autoload :Callbacks, "rubydora/callbacks"
|
17
18
|
autoload :ArrayWithCallback, "rubydora/array_with_callback"
|
19
|
+
autoload :Transactions, "rubydora/transactions"
|
18
20
|
|
19
21
|
|
20
22
|
require 'csv'
|
data/rubydora.gemspec
CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |s|
|
|
23
23
|
s.add_dependency "activesupport"
|
24
24
|
s.add_dependency "activemodel"
|
25
25
|
s.add_dependency "savon"
|
26
|
+
s.add_dependency "hooks"
|
27
|
+
s.add_dependency "deprecation"
|
26
28
|
|
27
29
|
s.add_development_dependency("rake")
|
28
30
|
s.add_development_dependency("shoulda")
|
@@ -15,6 +15,23 @@ describe "Integration testing against a live Fedora repository", :integration =>
|
|
15
15
|
@repository.ping.should == true
|
16
16
|
end
|
17
17
|
|
18
|
+
it "should ingest from foxml" do
|
19
|
+
@repository.find('changeme:n').delete rescue nil
|
20
|
+
pid = @repository.ingest :pid => 'changeme:n'
|
21
|
+
|
22
|
+
pid.should == 'changeme:n'
|
23
|
+
|
24
|
+
obj = @repository.find(pid)
|
25
|
+
obj.should_not be_new
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should ingest from foxml" do
|
29
|
+
pid = @repository.ingest :pid => 'new'
|
30
|
+
|
31
|
+
obj = @repository.find(pid)
|
32
|
+
obj.should_not be_new
|
33
|
+
@repository.find(pid).delete rescue nil
|
34
|
+
end
|
18
35
|
|
19
36
|
it "should create an object" do
|
20
37
|
obj = @repository.find('test:1')
|
@@ -138,6 +155,101 @@ describe "Integration testing against a live Fedora repository", :integration =>
|
|
138
155
|
obj.datastreams["my_ds"].mimeType.should == "application/x-text"
|
139
156
|
end
|
140
157
|
|
158
|
+
describe "with transactions" do
|
159
|
+
it "should work on ingest" do
|
160
|
+
@repository.find('transactions:1').delete rescue nil
|
161
|
+
|
162
|
+
@repository.transaction do |t|
|
163
|
+
obj = @repository.find('transactions:1')
|
164
|
+
obj.save
|
165
|
+
|
166
|
+
t.rollback
|
167
|
+
end
|
168
|
+
|
169
|
+
obj = @repository.find('transactions:1')
|
170
|
+
obj.should be_new
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should work on purge" do
|
174
|
+
@repository.find('transactions:1').delete rescue nil
|
175
|
+
|
176
|
+
obj = @repository.find('transactions:1')
|
177
|
+
obj.save
|
178
|
+
|
179
|
+
@repository.transaction do |t|
|
180
|
+
obj.delete
|
181
|
+
|
182
|
+
t.rollback
|
183
|
+
end
|
184
|
+
|
185
|
+
obj = @repository.find('transactions:1')
|
186
|
+
obj.should_not be_new
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should work on datastreams" do
|
190
|
+
@repository.find('transactions:1').delete rescue nil
|
191
|
+
|
192
|
+
obj = @repository.find('transactions:1')
|
193
|
+
obj.save
|
194
|
+
|
195
|
+
ds = obj.datastreams['datastream_to_delete']
|
196
|
+
ds.content = 'asdf'
|
197
|
+
ds.save
|
198
|
+
|
199
|
+
ds2 = obj.datastreams['datastream_to_change']
|
200
|
+
ds2.content = 'asdf'
|
201
|
+
ds2.save
|
202
|
+
|
203
|
+
ds3 = obj.datastreams['datastream_to_change_properties']
|
204
|
+
ds3.content = 'asdf'
|
205
|
+
ds3.versionable = true
|
206
|
+
ds3.dsState = 'I'
|
207
|
+
ds3.save
|
208
|
+
|
209
|
+
@repository.transaction do |t|
|
210
|
+
ds.delete
|
211
|
+
|
212
|
+
ds2.content = '1234'
|
213
|
+
ds2.save
|
214
|
+
|
215
|
+
@repository.set_datastream_options :pid => obj.pid, :dsid => 'datastream_to_change_properties', :state => 'A'
|
216
|
+
@repository.set_datastream_options :pid => obj.pid, :dsid => 'datastream_to_change_properties', :versionable => false
|
217
|
+
|
218
|
+
ds4 = obj.datastreams['datastream_to_create']
|
219
|
+
ds4.content = 'asdf'
|
220
|
+
ds4.save
|
221
|
+
|
222
|
+
t.rollback
|
223
|
+
end
|
224
|
+
|
225
|
+
obj = @repository.find('transactions:1')
|
226
|
+
obj.datastreams.keys.should_not include('datsatream_to_create')
|
227
|
+
obj.datastreams.keys.should include('datastream_to_delete')
|
228
|
+
obj.datastreams['datastream_to_change'].content.should == 'asdf'
|
229
|
+
obj.datastreams['datastream_to_change_properties'].versionable.should == true
|
230
|
+
obj.datastreams['datastream_to_change_properties'].dsState.should == 'I'
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should work on relationships" do
|
234
|
+
@repository.find('transactions:1').delete rescue nil
|
235
|
+
|
236
|
+
obj = @repository.find('transactions:1')
|
237
|
+
obj.save
|
238
|
+
@repository.add_relationship :subject => obj.pid, :predicate => 'uri:asdf', :object => 'fedora:object'
|
239
|
+
|
240
|
+
ds = obj.datastreams['RELS-EXT'].content
|
241
|
+
|
242
|
+
@repository.transaction do |t|
|
243
|
+
@repository.purge_relationship :subject => obj.pid, :predicate => 'uri:asdf', :object => 'fedora:object'
|
244
|
+
@repository.add_relationship :subject => obj.pid, :predicate => 'uri:qwerty', :object => 'fedora:object'
|
245
|
+
|
246
|
+
t.rollback
|
247
|
+
|
248
|
+
end
|
249
|
+
obj = @repository.find('transactions:1')
|
250
|
+
obj.datastreams['RELS-EXT'].content.should == ds
|
251
|
+
end
|
252
|
+
end
|
141
253
|
|
142
254
|
describe "object versions" do
|
143
255
|
it "should have versions" do
|
@@ -1,15 +1,52 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'loggable'
|
3
2
|
|
4
3
|
describe Rubydora::RestApiClient do
|
4
|
+
class FakeException < Exception
|
5
|
+
|
6
|
+
end
|
5
7
|
class MockRepository
|
6
8
|
include Rubydora::RestApiClient
|
7
9
|
include Loggable
|
8
10
|
|
9
|
-
|
10
11
|
attr_accessor :config
|
11
12
|
end
|
12
13
|
|
14
|
+
|
15
|
+
|
16
|
+
describe "exception handling" do
|
17
|
+
|
18
|
+
shared_examples "RestClient error handling" do
|
19
|
+
subject {
|
20
|
+
mock_repository = MockRepository.new
|
21
|
+
mock_repository.config = { :url => 'http://example.org' }
|
22
|
+
|
23
|
+
mock_repository
|
24
|
+
}
|
25
|
+
|
26
|
+
it "should replace a RestClient exception with a Rubydora one" do
|
27
|
+
subject.stub_chain(:client, :[], :get).and_raise RestClient::InternalServerError.new
|
28
|
+
subject.stub_chain(:client, :[], :put).and_raise RestClient::InternalServerError.new
|
29
|
+
subject.stub_chain(:client, :[], :delete).and_raise RestClient::InternalServerError.new
|
30
|
+
subject.stub_chain(:client, :[], :post).and_raise RestClient::InternalServerError.new
|
31
|
+
expect { subject.send(method, :pid => 'fake:pid', :dsid => 'my_dsid') }.to raise_error Rubydora::FedoraInvalidRequest
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
[:next_pid, :find_objects, :object, :ingest, :export, :modify_object, :purge_object, :object_versions, :object_xml, :datastream, :datastreams, :set_datastream_options, :datastream_versions, :datastream_history, :datastream_dissemination, :add_datastream, :modify_datastream, :purge_datastream, :relationships, :add_relationship, :purge_relationship, :dissemination].each do |method|
|
36
|
+
|
37
|
+
class_eval %Q{
|
38
|
+
describe "##{method}" do
|
39
|
+
it_behaves_like "RestClient error handling"
|
40
|
+
let(:method) { '#{method}' }
|
41
|
+
end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
|
13
50
|
before(:each) do
|
14
51
|
@fedora_user = 'fedoraAdmin'
|
15
52
|
@fedora_password = 'fedoraAdmin'
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rubydora::Transactions do
|
4
|
+
|
5
|
+
|
6
|
+
subject {
|
7
|
+
Rubydora::Repository.any_instance.stub(:version).and_return(100)
|
8
|
+
repository = Rubydora::Repository.new :url => 'http://example.org'
|
9
|
+
}
|
10
|
+
|
11
|
+
|
12
|
+
describe "#rollback" do
|
13
|
+
it "ingest" do
|
14
|
+
subject.client.stub_chain(:[], :post).and_return 'asdf'
|
15
|
+
subject.should_receive(:purge_object).with(hash_including(:pid => 'asdf'))
|
16
|
+
|
17
|
+
subject.transaction do |t|
|
18
|
+
|
19
|
+
subject.ingest :pid => 'asdf', :file => '<a />'
|
20
|
+
|
21
|
+
t.rollback
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "modify_object" do
|
26
|
+
subject.client.stub_chain(:[], :put).and_return 'asdf'
|
27
|
+
|
28
|
+
mock_object = double('Rubydora::DigitalObject', :state => 'A', :ownerId => '567', :logMessage => 'dfghj')
|
29
|
+
subject.should_receive(:find).with('asdf').and_return mock_object
|
30
|
+
|
31
|
+
|
32
|
+
subject.transaction do |t|
|
33
|
+
subject.modify_object :pid => 'asdf', :state => 'I', :ownerId => '123', :logMessage => 'changing asdf'
|
34
|
+
|
35
|
+
subject.should_receive(:modify_object).with(hash_including(:pid => 'asdf', :state => 'A', :ownerId => '567', :logMessage => 'reverting'))
|
36
|
+
t.rollback
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "purge_object" do
|
41
|
+
subject.client.stub_chain(:[], :delete)
|
42
|
+
|
43
|
+
subject.should_receive(:export).with(hash_including(:pid => 'asdf', :context => :archive)).and_return '<xml />'
|
44
|
+
subject.should_receive(:ingest).with(hash_including(:pid => 'asdf', :file => '<xml />'))
|
45
|
+
|
46
|
+
subject.transaction do |t|
|
47
|
+
subject.purge_object :pid => 'asdf'
|
48
|
+
|
49
|
+
t.rollback
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "add_datastream" do
|
54
|
+
subject.client.stub_chain(:[], :post)
|
55
|
+
subject.should_receive(:purge_datastream).with(hash_including(:pid => 'asdf', :dsid => 'mydsid'))
|
56
|
+
|
57
|
+
subject.transaction do |t|
|
58
|
+
subject.add_datastream :pid => 'asdf', :dsid => 'mydsid'
|
59
|
+
|
60
|
+
t.rollback
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it "modify_datastream" do
|
65
|
+
subject.client.stub_chain(:[], :put)
|
66
|
+
|
67
|
+
subject.should_receive(:export).with(hash_including(:pid => 'asdf', :context => :archive)).and_return '<xml />'
|
68
|
+
subject.should_receive(:ingest).with(hash_including(:pid => 'asdf', :file => '<xml />'))
|
69
|
+
|
70
|
+
subject.transaction do |t|
|
71
|
+
subject.modify_datastream :pid => 'asdf', :dsid => 'mydsid'
|
72
|
+
|
73
|
+
t.rollback
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "set_datastream_options" do
|
78
|
+
subject.client.stub_chain(:[], :put)
|
79
|
+
|
80
|
+
mock_object = double('Rubydora::DigitalObject')
|
81
|
+
mock_object.stub_chain(:datastreams, :[], :versionable).and_return(false)
|
82
|
+
subject.should_receive(:find).with('asdf').and_return mock_object
|
83
|
+
|
84
|
+
subject.transaction do |t|
|
85
|
+
subject.set_datastream_options :pid => 'asdf', :dsid => 'mydsid', :versionable => true
|
86
|
+
|
87
|
+
subject.should_receive(:set_datastream_options).with(hash_including(:pid => 'asdf', :versionable => false, :dsid => 'mydsid'))
|
88
|
+
|
89
|
+
t.rollback
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "purge_datastream" do
|
94
|
+
subject.client.stub_chain(:[], :delete)
|
95
|
+
|
96
|
+
subject.should_receive(:export).with(hash_including(:pid => 'asdf', :context => :archive)).and_return '<xml />'
|
97
|
+
subject.should_receive(:ingest).with(hash_including(:pid => 'asdf', :file => '<xml />'))
|
98
|
+
|
99
|
+
subject.transaction do |t|
|
100
|
+
subject.purge_datastream :pid => 'asdf', :dsid => 'mydsid'
|
101
|
+
|
102
|
+
t.rollback
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
it "add_relationship" do
|
107
|
+
subject.client.stub_chain(:[], :post)
|
108
|
+
subject.should_receive(:purge_relationship).with(hash_including(:subject => 'subject', :predicate => 'predicate', :object => 'object'))
|
109
|
+
|
110
|
+
subject.transaction do |t|
|
111
|
+
subject.add_relationship :subject => 'subject', :predicate => 'predicate', :object => 'object'
|
112
|
+
t.rollback
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it "purge_relationship" do
|
117
|
+
subject.client.stub_chain(:[], :delete)
|
118
|
+
subject.should_receive(:add_relationship).with(hash_including(:subject => 'subject', :predicate => 'predicate', :object => 'object'))
|
119
|
+
|
120
|
+
subject.transaction do |t|
|
121
|
+
subject.purge_relationship :subject => 'subject', :predicate => 'predicate', :object => 'object'
|
122
|
+
t.rollback
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubydora
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.11
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fastercsv
|
@@ -123,6 +123,38 @@ dependencies:
|
|
123
123
|
- - ! '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: hooks
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :runtime
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: deprecation
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :runtime
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
126
158
|
- !ruby/object:Gem::Dependency
|
127
159
|
name: rake
|
128
160
|
requirement: !ruby/object:Gem::Requirement
|
@@ -251,6 +283,7 @@ files:
|
|
251
283
|
- lib/rubydora/rest_api_client.rb
|
252
284
|
- lib/rubydora/rest_api_client/v33.rb
|
253
285
|
- lib/rubydora/soap.rb
|
286
|
+
- lib/rubydora/transactions.rb
|
254
287
|
- lib/rubydora/version.rb
|
255
288
|
- rubydora.gemspec
|
256
289
|
- spec/lib/datastream_spec.rb
|
@@ -263,6 +296,7 @@ files:
|
|
263
296
|
- spec/lib/resource_index_spec.rb
|
264
297
|
- spec/lib/rest_api_client_spec.rb
|
265
298
|
- spec/lib/soap_spec.rb
|
299
|
+
- spec/lib/transactions_spec.rb
|
266
300
|
- spec/spec_helper.rb
|
267
301
|
homepage: http://github.com/cbeer/rubydora
|
268
302
|
licenses: []
|
@@ -299,5 +333,6 @@ test_files:
|
|
299
333
|
- spec/lib/resource_index_spec.rb
|
300
334
|
- spec/lib/rest_api_client_spec.rb
|
301
335
|
- spec/lib/soap_spec.rb
|
336
|
+
- spec/lib/transactions_spec.rb
|
302
337
|
- spec/spec_helper.rb
|
303
338
|
has_rdoc:
|