rubydora 0.5.13 → 0.7.0
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/VERSION +1 -1
- data/lib/rubydora/datastream.rb +17 -4
- data/lib/rubydora/digital_object.rb +0 -1
- data/lib/rubydora/repository.rb +3 -7
- data/lib/rubydora/transactions.rb +18 -5
- data/lib/rubydora.rb +0 -3
- data/rubydora.gemspec +1 -2
- data/spec/lib/datastream_spec.rb +38 -2
- data/spec/lib/repository_spec.rb +2 -10
- data/spec/lib/transactions_spec.rb +26 -0
- metadata +4 -40
- data/lib/rubydora/ext/model_loader.rb +0 -62
- data/lib/rubydora/ext/solr.rb +0 -103
- data/lib/rubydora/ext.rb +0 -5
- data/lib/rubydora/extension_parameters.rb +0 -51
- data/lib/rubydora/rest_api_client/v33.rb +0 -27
- data/lib/rubydora/soap.rb +0 -20
- data/spec/lib/ext_model_loader_spec.rb +0 -6
- data/spec/lib/ext_solr_spec.rb +0 -144
- data/spec/lib/extension_parameters_spec.rb +0 -60
- data/spec/lib/soap_spec.rb +0 -12
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/lib/rubydora/datastream.rb
CHANGED
@@ -12,8 +12,6 @@ module Rubydora
|
|
12
12
|
class_attribute :eager_load_datastream_content
|
13
13
|
self.eager_load_datastream_content = false
|
14
14
|
|
15
|
-
include Rubydora::ExtensionParameters
|
16
|
-
|
17
15
|
attr_reader :digital_object, :dsid
|
18
16
|
|
19
17
|
# mapping datastream attributes (and api parameters) to datastream profile names
|
@@ -37,6 +35,7 @@ module Rubydora
|
|
37
35
|
|
38
36
|
class_eval %Q{
|
39
37
|
def #{attribute.to_s}= val
|
38
|
+
validate_#{attribute.to_s}!(val) if respond_to?(:validate_#{attribute.to_s}!, true)
|
40
39
|
#{attribute.to_s}_will_change! unless val == #{attribute.to_s}
|
41
40
|
@#{attribute.to_s} = val
|
42
41
|
end
|
@@ -125,6 +124,8 @@ module Rubydora
|
|
125
124
|
# Retrieve the content of the datastream (and cache it)
|
126
125
|
# @return [String]
|
127
126
|
def content
|
127
|
+
return @content if new?
|
128
|
+
|
128
129
|
begin
|
129
130
|
options = { :pid => pid, :dsid => dsid }
|
130
131
|
options[:asOfDateTime] = asOfDateTime if asOfDateTime
|
@@ -161,6 +162,14 @@ module Rubydora
|
|
161
162
|
changed_attributes['content'] = nil
|
162
163
|
end
|
163
164
|
|
165
|
+
def has_content?
|
166
|
+
return true unless new?
|
167
|
+
|
168
|
+
return !dsLocation.blank? if ['E','R'].include? controlGroup
|
169
|
+
|
170
|
+
!@content.blank?
|
171
|
+
end
|
172
|
+
|
164
173
|
# Retrieve the datastream profile as a hash (and cache it)
|
165
174
|
# @param opts [Hash] :validateChecksum if you want fedora to validate the checksum
|
166
175
|
# @return [Hash] see Fedora #getDatastream documentation for keys
|
@@ -224,7 +233,7 @@ module Rubydora
|
|
224
233
|
run_callbacks :create do
|
225
234
|
repository.add_datastream to_api_params.merge({ :pid => pid, :dsid => dsid })
|
226
235
|
reset_profile_attributes
|
227
|
-
|
236
|
+
self.class.new(digital_object, dsid, @options)
|
228
237
|
end
|
229
238
|
end
|
230
239
|
|
@@ -236,7 +245,7 @@ module Rubydora
|
|
236
245
|
return create if new?
|
237
246
|
repository.modify_datastream to_api_params.merge({ :pid => pid, :dsid => dsid })
|
238
247
|
reset_profile_attributes
|
239
|
-
|
248
|
+
self.class.new(digital_object, dsid, @options)
|
240
249
|
end
|
241
250
|
end
|
242
251
|
|
@@ -298,6 +307,10 @@ module Rubydora
|
|
298
307
|
raise "Can't change values on older versions" if @asOfDateTime
|
299
308
|
end
|
300
309
|
|
310
|
+
def validate_dsLocation! val
|
311
|
+
URI.parse(val) unless val.nil?
|
312
|
+
end
|
313
|
+
|
301
314
|
private
|
302
315
|
def attribute_will_change! *args
|
303
316
|
check_if_read_only
|
@@ -12,7 +12,6 @@ module Rubydora
|
|
12
12
|
define_model_callbacks :save, :create, :destroy
|
13
13
|
define_model_callbacks :initialize, :only => :after
|
14
14
|
include ActiveModel::Dirty
|
15
|
-
include Rubydora::ExtensionParameters
|
16
15
|
include Rubydora::ModelsMixin
|
17
16
|
include Rubydora::RelationshipsMixin
|
18
17
|
|
data/lib/rubydora/repository.rb
CHANGED
@@ -16,7 +16,7 @@ module Rubydora
|
|
16
16
|
# @option options [Boolean] :validateChecksum
|
17
17
|
def initialize options = {}
|
18
18
|
@config = options.symbolize_keys
|
19
|
-
|
19
|
+
check_repository_version!
|
20
20
|
end
|
21
21
|
|
22
22
|
# {include:DigitalObject.find}
|
@@ -97,15 +97,11 @@ module Rubydora
|
|
97
97
|
protected
|
98
98
|
|
99
99
|
# Load fallback API implementations for older versions of Fedora
|
100
|
-
def
|
100
|
+
def check_repository_version!
|
101
101
|
return unless version
|
102
102
|
|
103
|
-
if version <= 3.0
|
104
|
-
end
|
105
|
-
|
106
103
|
if version < 3.4
|
107
|
-
|
108
|
-
self.extend Rubydora::RestApiClient::V33
|
104
|
+
raise "You're connecting to a Fedora #{version} repository. Rubydora requires Fedora >= 3.4"
|
109
105
|
end
|
110
106
|
|
111
107
|
true
|
@@ -15,15 +15,15 @@ module Rubydora
|
|
15
15
|
end
|
16
16
|
|
17
17
|
before_purge_object do |options|
|
18
|
-
append_to_transactions_log :purge_object, :pid => options[:pid], :foxml =>
|
18
|
+
append_to_transactions_log :purge_object, :pid => options[:pid], :foxml => true if Rubydora::Transactions.use_transactions
|
19
19
|
end
|
20
20
|
|
21
21
|
before_modify_datastream do |options|
|
22
|
-
append_to_transactions_log :modify_datastream, :pid => options[:pid], :foxml =>
|
22
|
+
append_to_transactions_log :modify_datastream, :pid => options[:pid], :foxml => true if Rubydora::Transactions.use_transactions
|
23
23
|
end
|
24
24
|
|
25
25
|
before_purge_datastream do |options|
|
26
|
-
append_to_transactions_log :purge_datastream, :pid => options[:pid], :foxml =>
|
26
|
+
append_to_transactions_log :purge_datastream, :pid => options[:pid], :foxml => true if Rubydora::Transactions.use_transactions
|
27
27
|
end
|
28
28
|
|
29
29
|
before_add_datastream do |options|
|
@@ -72,15 +72,28 @@ module Rubydora
|
|
72
72
|
# Unshift a transaction entry onto the transaction logs.
|
73
73
|
# We want these entries in reverse-chronological order
|
74
74
|
# for ease of undoing..
|
75
|
-
def append_to_transactions_log
|
75
|
+
def append_to_transactions_log method, options = {}
|
76
76
|
return unless Rubydora::Transactions.use_transactions
|
77
|
-
|
77
|
+
|
78
|
+
unless transaction_is_redundant?(method, options)
|
79
|
+
options[:foxml] = export(:pid => options[:pid], :context => :archive) if options[:foxml] == true
|
80
|
+
transactions_log.unshift([method, options])
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
# The repository transaction log.
|
81
85
|
def transactions_log
|
82
86
|
@log ||= []
|
83
87
|
end
|
88
|
+
|
89
|
+
def transaction_is_redundant? method, options
|
90
|
+
return true if transactions_log.any? { |(t_method, t_options)|
|
91
|
+
# these methods will rollback ANY object change that happens after it, so there's no need to track future changes to this object
|
92
|
+
t_options[:pid] == options[:pid] and [:ingest, :purge_object, :modify_datastream, :purge_datastream].include? t_method
|
93
|
+
}
|
94
|
+
|
95
|
+
false
|
96
|
+
end
|
84
97
|
end
|
85
98
|
|
86
99
|
class Transaction
|
data/lib/rubydora.rb
CHANGED
@@ -8,12 +8,9 @@ module Rubydora
|
|
8
8
|
autoload :ResourceIndex, "rubydora/resource_index"
|
9
9
|
autoload :FedoraUrlHelpers, "rubydora/fedora_url_helpers"
|
10
10
|
autoload :RestApiClient, "rubydora/rest_api_client"
|
11
|
-
autoload :Soap, "rubydora/soap"
|
12
11
|
autoload :ModelsMixin, "rubydora/models_mixin"
|
13
|
-
autoload :Ext, "rubydora/ext"
|
14
12
|
autoload :RelationshipsMixin, "rubydora/relationships_mixin"
|
15
13
|
autoload :DigitalObject, "rubydora/digital_object"
|
16
|
-
autoload :ExtensionParameters, "rubydora/extension_parameters"
|
17
14
|
autoload :Callbacks, "rubydora/callbacks"
|
18
15
|
autoload :ArrayWithCallback, "rubydora/array_with_callback"
|
19
16
|
autoload :Transactions, "rubydora/transactions"
|
data/rubydora.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Chris Beer"]
|
9
9
|
s.email = ["chris@cbeer.info"]
|
10
10
|
s.summary = %q{Fedora Commons REST API ruby library }
|
11
|
-
s.description = %q{Fedora Commons REST API ruby library
|
11
|
+
s.description = %q{Fedora Commons REST API ruby library}
|
12
12
|
s.homepage = "http://github.com/cbeer/rubydora"
|
13
13
|
|
14
14
|
s.files = `git ls-files`.split("\n")
|
@@ -22,7 +22,6 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.add_dependency "mime-types"
|
23
23
|
s.add_dependency "activesupport"
|
24
24
|
s.add_dependency "activemodel"
|
25
|
-
s.add_dependency "savon"
|
26
25
|
s.add_dependency "hooks"
|
27
26
|
s.add_dependency "deprecation"
|
28
27
|
|
data/spec/lib/datastream_spec.rb
CHANGED
@@ -210,6 +210,30 @@ describe Rubydora::Datastream do
|
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
+
describe "has_content?" do
|
214
|
+
subject { Rubydora::Datastream.new mock(:pid => 'asdf'), 'asdf' }
|
215
|
+
it "should have content if it is persisted" do
|
216
|
+
subject.stub(:new? => false)
|
217
|
+
subject.should have_content
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should have content if it has content" do
|
221
|
+
subject.content = "123"
|
222
|
+
subject.should have_content
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should have content if it has a dsLocation" do
|
226
|
+
subject.dsLocation = "urn:abc"
|
227
|
+
subject.controlGroup = 'E'
|
228
|
+
subject.should have_content
|
229
|
+
end
|
230
|
+
|
231
|
+
it "should not have content otherwise" do
|
232
|
+
subject.stub(:content => nil)
|
233
|
+
subject.should_not have_content
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
213
237
|
describe "update" do
|
214
238
|
|
215
239
|
before(:each) do
|
@@ -390,7 +414,7 @@ describe Rubydora::Datastream do
|
|
390
414
|
end
|
391
415
|
|
392
416
|
it "should look in the object profile" do
|
393
|
-
subject.
|
417
|
+
subject.stub(:profile) { { method => 'qwerty' } }
|
394
418
|
subject.send(method).should == 'qwerty'
|
395
419
|
end
|
396
420
|
|
@@ -409,8 +433,20 @@ describe Rubydora::Datastream do
|
|
409
433
|
end
|
410
434
|
|
411
435
|
describe "#dsLocation" do
|
412
|
-
it_behaves_like "a datastream attribute"
|
436
|
+
it_behaves_like "a read-only datastream attribute"
|
413
437
|
let(:method) { 'dsLocation' }
|
438
|
+
|
439
|
+
subject { Rubydora::Datastream.new @mock_object, 'dsid' }
|
440
|
+
|
441
|
+
it "should reject invalid URIs" do
|
442
|
+
expect { subject.dsLocation = "this is a bad uri" }.to raise_error URI::InvalidURIError
|
443
|
+
end
|
444
|
+
|
445
|
+
it "should appear in the save request" do
|
446
|
+
@mock_repository.should_receive(:modify_datastream).with(hash_including(method.to_sym => 'http://example.com'))
|
447
|
+
subject.dsLocation = 'http://example.com'
|
448
|
+
subject.save
|
449
|
+
end
|
414
450
|
end
|
415
451
|
|
416
452
|
describe "#altIDs" do
|
data/spec/lib/repository_spec.rb
CHANGED
@@ -65,17 +65,9 @@ describe Rubydora::Repository do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
describe "load_api_abstraction" do
|
68
|
-
class ApiAbstractionTestClass < Rubydora::Repository
|
69
|
-
def version; 3.3; end
|
70
|
-
end
|
71
68
|
it "should load an abstraction layer for relationships for older versions of the fedora rest api" do
|
72
|
-
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should automatically load the SOAP endpoint when needed" do
|
77
|
-
@mock_repository = ApiAbstractionTestClass.new
|
78
|
-
@mock_repository.should be_a_kind_of(Rubydora::Soap)
|
69
|
+
Rubydora::Repository.any_instance.stub(:version).and_return(3.3)
|
70
|
+
expect { Rubydora::Repository.new }.to raise_error
|
79
71
|
end
|
80
72
|
end
|
81
73
|
|
@@ -8,6 +8,31 @@ describe Rubydora::Transactions do
|
|
8
8
|
repository = Rubydora::Repository.new :url => 'http://example.org'
|
9
9
|
}
|
10
10
|
|
11
|
+
describe "#transaction_is_redundant?" do
|
12
|
+
it "should throw away transactions messages if the object was ingested or purged previously" do
|
13
|
+
subject.client.stub_chain(:[], :post).and_return 'asdf'
|
14
|
+
subject.client.stub_chain(:[], :put).and_return 'asdf'
|
15
|
+
subject.client.stub_chain(:[], :delete)
|
16
|
+
|
17
|
+
# this should be squelched
|
18
|
+
subject.should_not_receive(:export).with(hash_including(:pid => 'asdf', :context => :archive)).and_return '<xml />'
|
19
|
+
|
20
|
+
subject.transaction do |t|
|
21
|
+
subject.ingest :pid => 'asdf', :file => '<a />'
|
22
|
+
subject.purge_object :pid => 'asdf'
|
23
|
+
subject.modify_datastream :pid => 'asdf', :dsid => 'mydsid'
|
24
|
+
|
25
|
+
|
26
|
+
subject.should_receive(:purge_object).with(hash_including(:pid => 'asdf'))
|
27
|
+
|
28
|
+
# this should be squelched
|
29
|
+
subject.should_not_receive(:ingest).with(hash_including(:pid => 'asdf', :file => '<a />'))
|
30
|
+
|
31
|
+
t.rollback
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
11
36
|
describe "#rollback" do
|
12
37
|
|
13
38
|
it "should fire a after_rollback hook" do
|
@@ -84,6 +109,7 @@ describe Rubydora::Transactions do
|
|
84
109
|
subject.client.stub_chain(:[], :put)
|
85
110
|
|
86
111
|
subject.should_receive(:export).with(hash_including(:pid => 'asdf', :context => :archive)).and_return '<xml />'
|
112
|
+
subject.should_receive(:purge_object).with(hash_including(:pid => 'asdf'))
|
87
113
|
subject.should_receive(:ingest).with(hash_including(:pid => 'asdf', :file => '<xml />'))
|
88
114
|
|
89
115
|
subject.transaction do |t|
|
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.
|
4
|
+
version: 0.7.0
|
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-12-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fastercsv
|
@@ -107,22 +107,6 @@ dependencies:
|
|
107
107
|
- - ! '>='
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
|
-
- !ruby/object:Gem::Dependency
|
111
|
-
name: savon
|
112
|
-
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ! '>='
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: '0'
|
118
|
-
type: :runtime
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ! '>='
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '0'
|
126
110
|
- !ruby/object:Gem::Dependency
|
127
111
|
name: hooks
|
128
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -251,7 +235,7 @@ dependencies:
|
|
251
235
|
- - ! '>='
|
252
236
|
- !ruby/object:Gem::Version
|
253
237
|
version: '0'
|
254
|
-
description:
|
238
|
+
description: Fedora Commons REST API ruby library
|
255
239
|
email:
|
256
240
|
- chris@cbeer.info
|
257
241
|
executables: []
|
@@ -271,31 +255,21 @@ files:
|
|
271
255
|
- lib/rubydora/callbacks.rb
|
272
256
|
- lib/rubydora/datastream.rb
|
273
257
|
- lib/rubydora/digital_object.rb
|
274
|
-
- lib/rubydora/ext.rb
|
275
|
-
- lib/rubydora/ext/model_loader.rb
|
276
|
-
- lib/rubydora/ext/solr.rb
|
277
|
-
- lib/rubydora/extension_parameters.rb
|
278
258
|
- lib/rubydora/fedora_url_helpers.rb
|
279
259
|
- lib/rubydora/models_mixin.rb
|
280
260
|
- lib/rubydora/relationships_mixin.rb
|
281
261
|
- lib/rubydora/repository.rb
|
282
262
|
- lib/rubydora/resource_index.rb
|
283
263
|
- lib/rubydora/rest_api_client.rb
|
284
|
-
- lib/rubydora/rest_api_client/v33.rb
|
285
|
-
- lib/rubydora/soap.rb
|
286
264
|
- lib/rubydora/transactions.rb
|
287
265
|
- lib/rubydora/version.rb
|
288
266
|
- rubydora.gemspec
|
289
267
|
- spec/lib/datastream_spec.rb
|
290
268
|
- spec/lib/digital_object_spec.rb
|
291
|
-
- spec/lib/ext_model_loader_spec.rb
|
292
|
-
- spec/lib/ext_solr_spec.rb
|
293
|
-
- spec/lib/extension_parameters_spec.rb
|
294
269
|
- spec/lib/integration_test_spec.rb
|
295
270
|
- spec/lib/repository_spec.rb
|
296
271
|
- spec/lib/resource_index_spec.rb
|
297
272
|
- spec/lib/rest_api_client_spec.rb
|
298
|
-
- spec/lib/soap_spec.rb
|
299
273
|
- spec/lib/transactions_spec.rb
|
300
274
|
- spec/spec_helper.rb
|
301
275
|
homepage: http://github.com/cbeer/rubydora
|
@@ -310,35 +284,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
310
284
|
- - ! '>='
|
311
285
|
- !ruby/object:Gem::Version
|
312
286
|
version: '0'
|
313
|
-
segments:
|
314
|
-
- 0
|
315
|
-
hash: -2331369473702813867
|
316
287
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
317
288
|
none: false
|
318
289
|
requirements:
|
319
290
|
- - ! '>='
|
320
291
|
- !ruby/object:Gem::Version
|
321
292
|
version: '0'
|
322
|
-
segments:
|
323
|
-
- 0
|
324
|
-
hash: -2331369473702813867
|
325
293
|
requirements: []
|
326
294
|
rubyforge_project:
|
327
|
-
rubygems_version: 1.8.
|
295
|
+
rubygems_version: 1.8.23
|
328
296
|
signing_key:
|
329
297
|
specification_version: 3
|
330
298
|
summary: Fedora Commons REST API ruby library
|
331
299
|
test_files:
|
332
300
|
- spec/lib/datastream_spec.rb
|
333
301
|
- spec/lib/digital_object_spec.rb
|
334
|
-
- spec/lib/ext_model_loader_spec.rb
|
335
|
-
- spec/lib/ext_solr_spec.rb
|
336
|
-
- spec/lib/extension_parameters_spec.rb
|
337
302
|
- spec/lib/integration_test_spec.rb
|
338
303
|
- spec/lib/repository_spec.rb
|
339
304
|
- spec/lib/resource_index_spec.rb
|
340
305
|
- spec/lib/rest_api_client_spec.rb
|
341
|
-
- spec/lib/soap_spec.rb
|
342
306
|
- spec/lib/transactions_spec.rb
|
343
307
|
- spec/spec_helper.rb
|
344
308
|
has_rdoc:
|
@@ -1,62 +0,0 @@
|
|
1
|
-
module Rubydora::Ext
|
2
|
-
# Rubydora extension to load dynamically load modules into an object based on defined models
|
3
|
-
module ModelLoader
|
4
|
-
# @param [Hash] args
|
5
|
-
# @option args [Class] :base_namespace
|
6
|
-
# @option args [Class] :method
|
7
|
-
# @option args [Class] :class
|
8
|
-
#
|
9
|
-
def self.load args = {}
|
10
|
-
args[:class] ||= Rubydora::DigitalObject
|
11
|
-
args[:method] ||= :models
|
12
|
-
|
13
|
-
args[:class].extension_parameters[:ModelLoaderMixin] ||= {}
|
14
|
-
args[:class].extension_parameters[:ModelLoaderMixin][:namespaces] ||= []
|
15
|
-
args[:class].extension_parameters[:ModelLoaderMixin][:namespaces] << args[:base_namespace]
|
16
|
-
args[:class].extension_parameters[:ModelLoaderMixin][:method] ||= args[:method]
|
17
|
-
args[:class].use_extension(ModelLoaderMixin)
|
18
|
-
end
|
19
|
-
|
20
|
-
module ModelLoaderMixin
|
21
|
-
# @param [Class] base
|
22
|
-
def self.extended(document)
|
23
|
-
self.module_names(document).each do |model|
|
24
|
-
document.class.extension_parameters[:ModelLoaderMixin][:namespaces].each do |ns|
|
25
|
-
begin
|
26
|
-
mod = self.string_to_constant [ns, model].compact.map { |x| x.to_s }.join("/")
|
27
|
-
document.send(:extend, mod)
|
28
|
-
rescue NameError, LoadError
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
# convert a model string to a Ruby class (see ActiveSupport::Inflector#constantize)
|
35
|
-
# @param [String] lower_case_and_underscored_word
|
36
|
-
# @return [Module]
|
37
|
-
def self.string_to_constant lower_case_and_underscored_word
|
38
|
-
camel_cased_word = lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
39
|
-
|
40
|
-
names = camel_cased_word.split('::')
|
41
|
-
names.shift if names.empty? || names.first.empty?
|
42
|
-
|
43
|
-
constant = Object
|
44
|
-
names.each do |name|
|
45
|
-
if Module.method(:const_get).arity == 1
|
46
|
-
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
47
|
-
else
|
48
|
-
constant = constant.const_defined?(name,false) ? constant.const_get(name) : constant.const_missing(name)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
constant
|
52
|
-
end
|
53
|
-
|
54
|
-
private
|
55
|
-
def self.module_names(document)
|
56
|
-
arr = document.send(document.class.extension_parameters[:ModelLoaderMixin][:method])
|
57
|
-
arr &&= [arr] unless arr.is_a? Array
|
58
|
-
arr.map { |x| x.gsub('info:fedora/', '').downcase.gsub(/[^a-z0-9_:]+/, '_').gsub(':', '/').gsub(/_{2,}/, '_').gsub(/^_|_$/, '') }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
data/lib/rubydora/ext/solr.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module Rubydora::Ext
|
2
|
-
# Mapping Fedora objects to Solr documents
|
3
|
-
module Solr
|
4
|
-
# load this module by mixing into appropriate modules
|
5
|
-
# @param [Hash] args
|
6
|
-
# @option args [Class] :digital_object
|
7
|
-
# @option args [Class] :datastream
|
8
|
-
def self.load args = { :digital_object => Rubydora::DigitalObject, :datastream => Rubydora::Datastream}
|
9
|
-
args[:digital_object].send(:include, Rubydora::Ext::Solr::DigitalObjectMixin) if args[:digital_object]
|
10
|
-
args[:datastream].send(:include, Rubydora::Ext::Solr::DatastreamMixin) if args[:datastream]
|
11
|
-
end
|
12
|
-
|
13
|
-
# Datastreams mixin
|
14
|
-
module DatastreamMixin
|
15
|
-
# Initialize solr mapping logic
|
16
|
-
# @param [Class] base
|
17
|
-
def self.included(base)
|
18
|
-
base.instance_eval %Q{
|
19
|
-
class << self; attr_accessor :solr_mapping_logic end
|
20
|
-
}
|
21
|
-
|
22
|
-
base.class_eval %Q{
|
23
|
-
attr_writer :solr_mapping_logic
|
24
|
-
def solr_mapping_logic
|
25
|
-
@solr_mapping_logic ||= self.class.solr_mapping_logic.dup
|
26
|
-
end
|
27
|
-
}
|
28
|
-
|
29
|
-
base.solr_mapping_logic ||= []
|
30
|
-
end
|
31
|
-
|
32
|
-
# sets appropriate solr document parameters for this datastream
|
33
|
-
# @param [Hash] doc Solr document object (pass-by-reference)
|
34
|
-
def to_solr(doc = {})
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
# DigitalObject mixin
|
40
|
-
module DigitalObjectMixin
|
41
|
-
# Initialize solr mapping logic
|
42
|
-
# @param [Class] base
|
43
|
-
def self.included(base)
|
44
|
-
base.instance_eval %Q{
|
45
|
-
class << self; attr_accessor :solr_mapping_logic end
|
46
|
-
}
|
47
|
-
|
48
|
-
base.class_eval %Q{
|
49
|
-
attr_writer :solr_mapping_logic
|
50
|
-
def solr_mapping_logic
|
51
|
-
@solr_mapping_logic ||= self.class.solr_mapping_logic.dup
|
52
|
-
end
|
53
|
-
}
|
54
|
-
|
55
|
-
base.solr_mapping_logic ||= [:object_profile_to_solr,:datastreams_to_solr, :relations_to_solr]
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Set appropriate solr document attributes for this object
|
60
|
-
# @param [Hash] doc Solr document object (pass-by-reference)
|
61
|
-
def to_solr(doc = {})
|
62
|
-
self.solr_mapping_logic.each do |method_name|
|
63
|
-
send(method_name, doc)
|
64
|
-
end
|
65
|
-
|
66
|
-
doc.reject { |k,v| v.nil? or (v.respond_to?(:empty?) and v.empty?) }
|
67
|
-
end
|
68
|
-
|
69
|
-
# add solr document attributes from the object profile
|
70
|
-
# @param [Hash] doc Solr document object (pass-by-reference)
|
71
|
-
def object_profile_to_solr doc
|
72
|
-
doc['id'] = pid
|
73
|
-
doc['pid_s'] = pid
|
74
|
-
|
75
|
-
self.profile.each do |key, value|
|
76
|
-
doc["#{key}_s"] = value
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
# add solr document attributes from the object datastreams
|
81
|
-
# @param [Hash] doc Solr document object (pass-by-reference)
|
82
|
-
def datastreams_to_solr doc
|
83
|
-
datastreams.each do |dsid, ds|
|
84
|
-
doc['disseminates_s'] ||= []
|
85
|
-
doc['disseminates_s'] << dsid
|
86
|
-
ds.to_solr(doc)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# add solr document attributes by querying the resource index
|
91
|
-
# @param [Hash] doc Solr document object (pass-by-reference)
|
92
|
-
def relations_to_solr doc
|
93
|
-
self.repository.sparql("SELECT ?relation ?object FROM <#ri> WHERE {
|
94
|
-
<#{uri}> ?relation ?object
|
95
|
-
}").each do |row|
|
96
|
-
solr_field = "ri_#{row['relation'].split('#').last}_s"
|
97
|
-
doc[solr_field] ||= []
|
98
|
-
doc[solr_field] << row['object']
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
data/lib/rubydora/ext.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
module Rubydora
|
2
|
-
# Copied in part from projectblacklight.org
|
3
|
-
module ExtensionParameters
|
4
|
-
# setup extension support
|
5
|
-
def self.included(base)
|
6
|
-
base.extend ExtendableClassMethods
|
7
|
-
|
8
|
-
base.class_eval do
|
9
|
-
# Provide a class-level hash for extension parameters
|
10
|
-
# @return [Hash]
|
11
|
-
def self.extension_parameters
|
12
|
-
## This variable should NOT be @@, since we're in a class method,
|
13
|
-
# it's just @ to be a class variable. Confusing, but it
|
14
|
-
# passes the tests this way.
|
15
|
-
@extension_parameters ||= {}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
base.after_initialize do
|
20
|
-
apply_extensions
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# try to apply registered extensions
|
25
|
-
def apply_extensions
|
26
|
-
self.class.registered_extensions.each do |registration|
|
27
|
-
self.extend( registration[:module_obj] ) if registration[:condition_proc].nil? || registration[:condition_proc].call( self )
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Certain class-level modules needed for the document-specific
|
32
|
-
# extendability architecture
|
33
|
-
module ExtendableClassMethods
|
34
|
-
attr_writer :registered_extensions
|
35
|
-
|
36
|
-
# registered_extensions accessor
|
37
|
-
# @return [Array]
|
38
|
-
def registered_extensions
|
39
|
-
@registered_extensions ||= []
|
40
|
-
end
|
41
|
-
|
42
|
-
# register extensions
|
43
|
-
# @param [Module] module_obj
|
44
|
-
# @yield &condition
|
45
|
-
def use_extension( module_obj, &condition )
|
46
|
-
registered_extensions << {:module_obj => module_obj, :condition_proc => condition}
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module Rubydora::RestApiClient
|
2
|
-
# Fall-back implementations for fcrepo < 3.4
|
3
|
-
module V33
|
4
|
-
# @param [Rubydora::Repository] repository
|
5
|
-
def self.extended repository
|
6
|
-
repository.send(:extend, Rubydora::Soap)
|
7
|
-
end
|
8
|
-
|
9
|
-
# {include:RestApiClient#relationships}
|
10
|
-
def relationships options = {}
|
11
|
-
nil
|
12
|
-
end
|
13
|
-
|
14
|
-
# {include:RestApiClient#add_relationship}
|
15
|
-
def add_relationship options = {}
|
16
|
-
pid = options.delete(:pid) || options[:subject]
|
17
|
-
self.soap.request :add_relationship, :pid => pid, :relationship => options[:predicate], :object => options[:object], :isLiteral => false, :datatype => nil
|
18
|
-
end
|
19
|
-
|
20
|
-
# {include:RestApiClient#purge_relationship}
|
21
|
-
def purge_relationship options = {}
|
22
|
-
pid = options.delete(:pid) || options[:subject]
|
23
|
-
self.soap.request :purge_relationship, :pid => pid, :relationship => options[:predicate], :object => options[:object], :isLiteral => false, :datatype => nil
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
data/lib/rubydora/soap.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Rubydora
|
2
|
-
# Fedora SOAP API extension
|
3
|
-
module Soap
|
4
|
-
# @param [Rubydora::Repository] repository
|
5
|
-
def self.extended repository
|
6
|
-
require 'savon'
|
7
|
-
end
|
8
|
-
|
9
|
-
# SOAP API endpoint
|
10
|
-
# @return [SOAP::RPC::Driver]
|
11
|
-
def soap
|
12
|
-
@soap ||= begin
|
13
|
-
client = Savon::Client.new do |wsdl, http|
|
14
|
-
wsdl.document = "#{ config[:url] }/wsdl?api=API-M"
|
15
|
-
http.auth.basic config[:user], config[:password]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/spec/lib/ext_solr_spec.rb
DELETED
@@ -1,144 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'rubydora/ext/solr'
|
3
|
-
|
4
|
-
describe Rubydora::Ext::Solr do
|
5
|
-
before(:all) do
|
6
|
-
Rubydora::Ext::Solr.load
|
7
|
-
end
|
8
|
-
describe "load" do
|
9
|
-
it "should load mixins" do
|
10
|
-
@mock_repository = mock(Rubydora::Repository)
|
11
|
-
obj = Rubydora::DigitalObject.new('pid', @mock_repository)
|
12
|
-
obj.should be_a_kind_of(Rubydora::Ext::Solr::DigitalObjectMixin)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
describe "solr_mapping_logic" do
|
17
|
-
class MockSolrMappingClass
|
18
|
-
|
19
|
-
end
|
20
|
-
before(:each) do
|
21
|
-
Rubydora::Ext::Solr.load :digital_object => MockSolrMappingClass
|
22
|
-
end
|
23
|
-
|
24
|
-
it "should provide a class-level step list" do
|
25
|
-
MockSolrMappingClass.solr_mapping_logic.should_not be_empty
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should be overridable on the class level" do
|
29
|
-
expect { MockSolrMappingClass.solr_mapping_logic << :a }.to change{MockSolrMappingClass.solr_mapping_logic.length}.by(1)
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should be overridable on the instance level" do
|
33
|
-
MockSolrMappingClass.solr_mapping_logic = []
|
34
|
-
mock = MockSolrMappingClass.new
|
35
|
-
|
36
|
-
mock.solr_mapping_logic.should be_empty
|
37
|
-
mock.solr_mapping_logic << :a
|
38
|
-
mock.solr_mapping_logic.should == [:a]
|
39
|
-
MockSolrMappingClass.solr_mapping_logic.should == []
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
describe "to_solr" do
|
45
|
-
before(:each) do
|
46
|
-
@mock_repository = mock(Rubydora::Repository)
|
47
|
-
@object = Rubydora::DigitalObject.new('pid', @mock_repository)
|
48
|
-
end
|
49
|
-
it "should call the members of solr_mapping_logic" do
|
50
|
-
@object.should_receive(:solr_mapping_logic).and_return([:mock_solr_step, :another_mock_solr_step])
|
51
|
-
@object.should_receive(:mock_solr_step)
|
52
|
-
@object.should_receive(:another_mock_solr_step)
|
53
|
-
@object.to_solr
|
54
|
-
end
|
55
|
-
|
56
|
-
it "should allow steps to modify the resulting solr document" do
|
57
|
-
@object.should_receive(:solr_mapping_logic).and_return([:mock_solr_step, :another_mock_solr_step])
|
58
|
-
@object.stub(:mock_solr_step) do |doc|
|
59
|
-
doc[:a] = 'a'
|
60
|
-
doc[:b] = 0
|
61
|
-
end
|
62
|
-
|
63
|
-
@object.stub(:another_mock_solr_step) do |doc|
|
64
|
-
doc[:b] = 'b'
|
65
|
-
end
|
66
|
-
|
67
|
-
@object.to_solr.should == { :a => 'a', :b => 'b'}
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "object_profile_to_solr" do
|
72
|
-
before(:each) do
|
73
|
-
@mock_repository = mock(Rubydora::Repository)
|
74
|
-
@object = Rubydora::DigitalObject.new('pid', @mock_repository)
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should map the pid and id" do
|
78
|
-
@object.should_receive(:profile).and_return({})
|
79
|
-
doc = {}
|
80
|
-
@object.object_profile_to_solr(doc)
|
81
|
-
|
82
|
-
doc['id'].should == 'pid'
|
83
|
-
doc['pid_s'].should == 'pid'
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should map the profile hash to generic document fields" do
|
87
|
-
@object.should_receive(:profile).and_return({'a' => 1, 'b' => 2})
|
88
|
-
doc = {}
|
89
|
-
@object.object_profile_to_solr(doc)
|
90
|
-
doc['a_s'].should == 1
|
91
|
-
doc['b_s'].should == 2
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "datastreams_to_solr" do
|
96
|
-
before(:each) do
|
97
|
-
@mock_repository = mock(Rubydora::Repository)
|
98
|
-
@object = Rubydora::DigitalObject.new('pid', @mock_repository)
|
99
|
-
end
|
100
|
-
|
101
|
-
it "should map the list of datastreams" do
|
102
|
-
@mock_ds = mock(Rubydora::Datastream)
|
103
|
-
@mock_ds2 = mock(Rubydora::Datastream)
|
104
|
-
|
105
|
-
@mock_ds.should_receive(:to_solr).with(instance_of(Hash))
|
106
|
-
@mock_ds2.should_receive(:to_solr).with(instance_of(Hash))
|
107
|
-
@object.should_receive(:datastreams).and_return(:a => @mock_ds, :b => @mock_ds2)
|
108
|
-
doc = {}
|
109
|
-
@object.datastreams_to_solr(doc)
|
110
|
-
|
111
|
-
doc['disseminates_s'].should == [:a, :b]
|
112
|
-
end
|
113
|
-
|
114
|
-
it "should let the datastreams inject any document attributes" do
|
115
|
-
@mock_ds = mock(Rubydora::Datastream)
|
116
|
-
|
117
|
-
@mock_ds.should_receive(:to_solr) do |doc|
|
118
|
-
doc['a'] = 1
|
119
|
-
end
|
120
|
-
@object.should_receive(:datastreams).and_return(:a => @mock_ds)
|
121
|
-
doc = {}
|
122
|
-
@object.datastreams_to_solr(doc)
|
123
|
-
|
124
|
-
doc['a'].should == 1
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
describe "relations_to_solr" do
|
129
|
-
before(:each) do
|
130
|
-
@mock_repository = mock(Rubydora::Repository)
|
131
|
-
@object = Rubydora::DigitalObject.new('pid', @mock_repository)
|
132
|
-
end
|
133
|
-
|
134
|
-
it "should lazily map relationships from SPARQL" do
|
135
|
-
@object.repository.should_receive(:sparql).and_return([{'relation' => '...#isPartOf', 'object' => 'info:fedora/test:pid'}])
|
136
|
-
doc = {}
|
137
|
-
@object.relations_to_solr(doc)
|
138
|
-
doc['ri_isPartOf_s'].should == ['info:fedora/test:pid']
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
|
143
|
-
end
|
144
|
-
|
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Rubydora::ExtensionParameters do
|
4
|
-
describe "extension parameters" do
|
5
|
-
class MockExtensionParametersClass
|
6
|
-
include Rubydora::Callbacks
|
7
|
-
register_callback :after_initialize
|
8
|
-
include Rubydora::ExtensionParameters
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should have extension parameters at the class level" do
|
12
|
-
MockExtensionParametersClass.extension_parameters[:a] = 1
|
13
|
-
|
14
|
-
MockExtensionParametersClass.extension_parameters.should == { :a => 1 }
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "DigitalObject" do
|
20
|
-
module FakeExtension
|
21
|
-
end
|
22
|
-
|
23
|
-
module OtherFakeExtension
|
24
|
-
|
25
|
-
end
|
26
|
-
before(:each) do
|
27
|
-
@mock_repository = mock()
|
28
|
-
end
|
29
|
-
|
30
|
-
after(:each) do
|
31
|
-
Rubydora::DigitalObject.registered_extensions = []
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should be extendable" do
|
35
|
-
Rubydora::DigitalObject.use_extension FakeExtension
|
36
|
-
@object = Rubydora::DigitalObject.new 'pid', @mock_repository
|
37
|
-
@object.is_a?(FakeExtension).should == true
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should be extendable conditionally" do
|
41
|
-
Rubydora::DigitalObject.use_extension(FakeExtension) { |x| true }
|
42
|
-
Rubydora::DigitalObject.use_extension(OtherFakeExtension) { |x| false }
|
43
|
-
@object = Rubydora::DigitalObject.new 'pid', @mock_repository
|
44
|
-
@object.is_a?(FakeExtension).should == true
|
45
|
-
@object.is_a?(OtherFakeExtension).should == false
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should be able to introspect object profiles" do
|
49
|
-
@mock_repository.should_receive(:object).any_number_of_times.with({:pid => 'pid'}).and_return <<-XML
|
50
|
-
<objectProfile>
|
51
|
-
<a>1</a>
|
52
|
-
</objectProfile>
|
53
|
-
XML
|
54
|
-
Rubydora::DigitalObject.use_extension(FakeExtension) { |x| x.profile['a'] == '1' }
|
55
|
-
@object = Rubydora::DigitalObject.new 'pid', @mock_repository
|
56
|
-
@object.is_a?(FakeExtension).should == true
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
data/spec/lib/soap_spec.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Rubydora::Soap do
|
4
|
-
before(:all) do
|
5
|
-
@repository = Rubydora.connect({ :url => 'http://localhost:8080/fedora', :user => 'fedoraAdmin', :password => 'fedoraAdmin' })
|
6
|
-
@repository.send(:extend, Rubydora::Soap)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should provide a SOAP endpoint accessor" do
|
10
|
-
@repository.soap.should be_a_kind_of(Savon::Client)
|
11
|
-
end
|
12
|
-
end
|