rubydora 0.5.13 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|