valkyrie 1.1.2 → 1.2.0.rc1

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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +1 -1
  3. data/.rubocop_todo.yml +5 -0
  4. data/CHANGELOG.md +28 -0
  5. data/README.md +43 -7
  6. data/db/migrate/20180802220739_add_optimistic_locking_to_orm_resources.rb +6 -0
  7. data/lib/generators/valkyrie/templates/resource.rb.erb +0 -1
  8. data/lib/valkyrie/change_set.rb +4 -0
  9. data/lib/valkyrie/id.rb +5 -0
  10. data/lib/valkyrie/metadata_adapter.rb +1 -0
  11. data/lib/valkyrie/persistence/composite_persister.rb +12 -1
  12. data/lib/valkyrie/persistence/fedora/list_node.rb +3 -3
  13. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +4 -0
  14. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +5 -0
  15. data/lib/valkyrie/persistence/fedora/persister/alternate_identifier.rb +0 -1
  16. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +2 -0
  17. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +33 -3
  18. data/lib/valkyrie/persistence/fedora/persister.rb +57 -16
  19. data/lib/valkyrie/persistence/fedora/query_service.rb +2 -0
  20. data/lib/valkyrie/persistence/fedora.rb +2 -0
  21. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +4 -0
  22. data/lib/valkyrie/persistence/memory/persister.rb +37 -14
  23. data/lib/valkyrie/persistence/memory/query_service.rb +2 -0
  24. data/lib/valkyrie/persistence/optimistic_lock_token.rb +34 -0
  25. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +11 -2
  26. data/lib/valkyrie/persistence/postgres/orm_converter.rb +35 -5
  27. data/lib/valkyrie/persistence/postgres/persister.rb +10 -12
  28. data/lib/valkyrie/persistence/postgres/query_service.rb +5 -4
  29. data/lib/valkyrie/persistence/postgres/resource_converter.rb +21 -1
  30. data/lib/valkyrie/persistence/postgres/resource_factory.rb +22 -18
  31. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +5 -1
  32. data/lib/valkyrie/persistence/solr/model_converter.rb +32 -2
  33. data/lib/valkyrie/persistence/solr/orm_converter.rb +22 -5
  34. data/lib/valkyrie/persistence/solr/persister.rb +2 -0
  35. data/lib/valkyrie/persistence/solr/query_service.rb +2 -0
  36. data/lib/valkyrie/persistence/solr/repository.rb +21 -8
  37. data/lib/valkyrie/persistence/solr/resource_factory.rb +6 -3
  38. data/lib/valkyrie/persistence.rb +10 -3
  39. data/lib/valkyrie/resource/access_controls.rb +0 -1
  40. data/lib/valkyrie/resource.rb +31 -8
  41. data/lib/valkyrie/specs/shared_specs/change_set_persister.rb +0 -1
  42. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +9 -0
  43. data/lib/valkyrie/specs/shared_specs/persister.rb +134 -7
  44. data/lib/valkyrie/specs/shared_specs/queries.rb +20 -2
  45. data/lib/valkyrie/specs/shared_specs/resource.rb +0 -1
  46. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +0 -1
  47. data/lib/valkyrie/storage/fedora.rb +29 -20
  48. data/lib/valkyrie/types.rb +11 -1
  49. data/lib/valkyrie/version.rb +1 -1
  50. data/lib/valkyrie.rb +0 -2
  51. metadata +7 -6
  52. data/config/fedora.yml +0 -10
@@ -4,12 +4,11 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
4
4
  raise 'persister must be set with `let(:persister)`' unless defined? persister
5
5
  class CustomResource < Valkyrie::Resource
6
6
  include Valkyrie::Resource::AccessControls
7
- attribute :id, Valkyrie::Types::ID.optional
8
7
  attribute :title
9
8
  attribute :author
10
9
  attribute :member_ids
11
10
  attribute :nested_resource
12
- attribute :single_value, Valkyrie::Types::String
11
+ attribute :single_value, Valkyrie::Types::String.optional
13
12
  end
14
13
  end
15
14
  after do
@@ -31,16 +30,12 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
31
30
  expect(saved.id).not_to be_blank
32
31
  end
33
32
 
34
- it "does not save non-array properties" do
35
- resource.single_value = "A Single Value"
36
- expect { persister.save(resource: resource) }.to raise_error ::Valkyrie::Persistence::UnsupportedDatatype
37
- end
38
-
39
33
  it "can save multiple resources at once" do
40
34
  resource2 = resource_class.new
41
35
  results = persister.save_all(resources: [resource, resource2])
42
36
 
43
37
  expect(results.map(&:id).uniq.length).to eq 2
38
+ expect(persister.save_all(resources: [])).to eq []
44
39
  end
45
40
 
46
41
  it "can save nested resources" do
@@ -51,6 +46,20 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
51
46
  expect(reloaded.nested_resource.first.title).to eq ["Nested"]
52
47
  end
53
48
 
49
+ it "can persist single values" do
50
+ resource.single_value = "A single value"
51
+
52
+ output = persister.save(resource: resource)
53
+
54
+ expect(output.single_value).to eq "A single value"
55
+ end
56
+
57
+ it "returns nil for an unset single value" do
58
+ output = persister.save(resource: resource_class.new)
59
+
60
+ expect(output.single_value).to be_nil
61
+ end
62
+
54
63
  it "can mix properties with nested resources" do
55
64
  pending "No support for mixed nesting." if flags.include?(:no_mixed_nesting)
56
65
  book2 = resource_class.new(title: "Nested", id: SecureRandom.uuid)
@@ -281,4 +290,122 @@ RSpec.shared_examples 'a Valkyrie::Persister' do |*flags|
281
290
  persister.wipe!
282
291
  expect(query_service.find_all.to_a.length).to eq 0
283
292
  end
293
+
294
+ context "optimistic locking" do
295
+ before do
296
+ class MyLockingResource < Valkyrie::Resource
297
+ enable_optimistic_locking
298
+ attribute :title
299
+ end
300
+ end
301
+
302
+ after do
303
+ ActiveSupport::Dependencies.remove_constant("MyLockingResource")
304
+ end
305
+
306
+ describe "#save" do
307
+ context "when creating a resource" do
308
+ it "returns the value of the system-generated optimistic locking attribute on the resource" do
309
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
310
+ saved_resource = persister.save(resource: resource)
311
+ expect(saved_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
312
+ end
313
+ end
314
+
315
+ context "when updating a resource with a correct lock token" do
316
+ it "successfully saves the resource and returns the updated value of the optimistic locking attribute" do
317
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
318
+ initial_resource = persister.save(resource: resource)
319
+ updated_resource = persister.save(resource: initial_resource)
320
+ expect(initial_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK])
321
+ .not_to eq updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
322
+ end
323
+ end
324
+
325
+ context "when updating a resource with an incorrect lock token" do
326
+ it "raises a Valkyrie::Persistence::StaleObjectError" do
327
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
328
+ resource = persister.save(resource: resource)
329
+ # update the resource in the datastore to make its token stale
330
+ persister.save(resource: resource)
331
+
332
+ expect { persister.save(resource: resource) }.to raise_error(Valkyrie::Persistence::StaleObjectError, resource.id.to_s)
333
+ end
334
+ end
335
+
336
+ context "when lock token is nil" do
337
+ it "successfully saves the resource and returns the updated value of the optimistic locking attribute" do
338
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
339
+ initial_resource = persister.save(resource: resource)
340
+ initial_token = initial_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first
341
+ initial_resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", [])
342
+ updated_resource = persister.save(resource: initial_resource)
343
+ expect(initial_token.serialize)
344
+ .not_to eq(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first.serialize)
345
+ expect(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
346
+ end
347
+ end
348
+
349
+ context "when there is a token, but it's for a different adapter (migration use case)" do
350
+ it "successfully saves the resource and returns a token for the adapter that was saved to" do
351
+ resource = MyLockingResource.new(title: ["My Locked Resource"])
352
+ initial_resource = persister.save(resource: resource)
353
+ new_token = Valkyrie::Persistence::OptimisticLockToken.new(
354
+ adapter_id: Valkyrie::ID.new("fake_adapter"),
355
+ token: "token"
356
+ )
357
+ initial_resource.send("#{Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK}=", [new_token])
358
+ updated_resource = persister.save(resource: initial_resource)
359
+ expect(new_token.serialize)
360
+ .not_to eq(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first.serialize)
361
+ expect(updated_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
362
+ end
363
+ end
364
+ end
365
+
366
+ describe "#save_all" do
367
+ context "when creating multiple resources" do
368
+ it "returns an array of resources with their system-generated optimistic locking attributes" do
369
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
370
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
371
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
372
+ saved_resources = persister.save_all(resources: [resource1, resource2, resource3])
373
+ saved_resources.each do |saved_resource|
374
+ expect(saved_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
375
+ end
376
+ end
377
+ end
378
+
379
+ context "when updating multiple resources that all have a correct lock token" do
380
+ it "saves the resources and returns them with updated values of the optimistic locking attribute" do
381
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
382
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
383
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
384
+ saved_resources = persister.save_all(resources: [resource1, resource2, resource3])
385
+ initial_lock_tokens = saved_resources.map do |r|
386
+ r[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
387
+ end
388
+ updated_resources = persister.save_all(resources: saved_resources)
389
+ updated_lock_tokens = updated_resources.map do |r|
390
+ r[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
391
+ end
392
+ expect(initial_lock_tokens & updated_lock_tokens).to be_empty
393
+ end
394
+ end
395
+
396
+ context "when one of the resources has an incorrect lock token" do
397
+ it "raises a Valkyrie::Persistence::StaleObjectError" do
398
+ resource1 = MyLockingResource.new(title: ["My Locked Resource 1"])
399
+ resource2 = MyLockingResource.new(title: ["My Locked Resource 2"])
400
+ resource3 = MyLockingResource.new(title: ["My Locked Resource 3"])
401
+ resource1, resource2, resource3 = persister.save_all(resources: [resource1, resource2, resource3])
402
+ # update a resource in the datastore to make its token stale
403
+ persister.save(resource: resource2)
404
+
405
+ expect { persister.save_all(resources: [resource1, resource2, resource3]) }
406
+ .to raise_error(Valkyrie::Persistence::StaleObjectError, "Valkyrie::Persistence::StaleObjectError")
407
+ end
408
+ end
409
+ end
410
+ end
284
411
  end
@@ -4,14 +4,12 @@ RSpec.shared_examples 'a Valkyrie query provider' do
4
4
  raise 'adapter must be set with `let(:adapter)`' unless
5
5
  defined? adapter
6
6
  class CustomResource < Valkyrie::Resource
7
- attribute :id, Valkyrie::Types::ID.optional
8
7
  attribute :alternate_ids, Valkyrie::Types::Array
9
8
  attribute :title
10
9
  attribute :member_ids, Valkyrie::Types::Array
11
10
  attribute :a_member_of
12
11
  end
13
12
  class SecondResource < Valkyrie::Resource
14
- attribute :id, Valkyrie::Types::ID.optional
15
13
  end
16
14
  end
17
15
  after do
@@ -291,4 +289,24 @@ RSpec.shared_examples 'a Valkyrie query provider' do
291
289
  expect(query_service.custom_queries.find_by_user_id).to eq 1
292
290
  end
293
291
  end
292
+
293
+ context "optimistic locking" do
294
+ before do
295
+ class CustomLockingQueryResource < Valkyrie::Resource
296
+ enable_optimistic_locking
297
+ attribute :title
298
+ end
299
+ end
300
+ after do
301
+ Object.send(:remove_const, :CustomLockingQueryResource)
302
+ end
303
+
304
+ it "retrieves the lock token and casts it to optimistic_lock_token attribute" do
305
+ resource = CustomLockingQueryResource.new(title: "My Title")
306
+ resource = persister.save(resource: resource)
307
+ resource = query_service.find_by(id: resource.id)
308
+ # we can't know the value in the general case
309
+ expect(resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]).not_to be_empty
310
+ end
311
+ end
294
312
  end
@@ -53,7 +53,6 @@ RSpec.shared_examples 'a Valkyrie::Resource' do
53
53
  describe "#human_readable_type" do
54
54
  before do
55
55
  class MyCustomResource < Valkyrie::Resource
56
- attribute :id, Valkyrie::Types::ID.optional
57
56
  attribute :title, Valkyrie::Types::Set
58
57
  end
59
58
  end
@@ -6,7 +6,6 @@ RSpec.shared_examples 'a Valkyrie::StorageAdapter' do
6
6
  raise 'file must be set with `let(:file)`' unless
7
7
  defined? file
8
8
  class CustomResource < Valkyrie::Resource
9
- attribute :id, Valkyrie::Types::ID.optional
10
9
  end
11
10
  end
12
11
  after do
@@ -2,10 +2,13 @@
2
2
  module Valkyrie::Storage
3
3
  # Implements the DataMapper Pattern to store binary data in fedora
4
4
  class Fedora
5
- attr_reader :connection
5
+ attr_reader :connection, :base_path
6
6
  PROTOCOL = 'fedora://'
7
- def initialize(connection:)
7
+
8
+ # @param [Ldp::Client] connection
9
+ def initialize(connection:, base_path: "/")
8
10
  @connection = connection
11
+ @base_path = base_path
9
12
  end
10
13
 
11
14
  # @param id [Valkyrie::ID]
@@ -29,14 +32,13 @@ module Valkyrie::Storage
29
32
  # @param resource [Valkyrie::Resource]
30
33
  # @return [Valkyrie::StorageAdapter::StreamFile]
31
34
  def upload(file:, original_filename:, resource:)
32
- # TODO: this is a very naive aproach. Change to PCDM
33
- identifier = resource.id.to_uri + '/original'
34
- ActiveFedora::File.new(identifier) do |af|
35
- af.content = file
36
- af.original_name = original_filename
37
- af.save!
38
- af.metadata.set_value(:type, af.metadata.type + [::RDF::URI('http://pcdm.org/use#OriginalFile')])
39
- af.metadata.save
35
+ identifier = id_to_uri(resource.id) + '/original'
36
+ connection.http.put do |request|
37
+ request.url identifier
38
+ request.headers['Content-Type'] = file.content_type
39
+ request.headers['Content-Disposition'] = "attachment; filename=\"#{original_filename}\""
40
+ request.headers['digest'] = "sha1=#{Digest::SHA1.file(file)}"
41
+ request.body = file.tempfile.read
40
42
  end
41
43
  find_by(id: Valkyrie::ID.new(identifier.to_s.sub(/^.+\/\//, PROTOCOL)))
42
44
  end
@@ -44,22 +46,22 @@ module Valkyrie::Storage
44
46
  # Delete the file in Fedora associated with the given identifier.
45
47
  # @param id [Valkyrie::ID]
46
48
  def delete(id:)
47
- ActiveFedora::File.new(active_fedora_identifier(id: id)).ldp_source.delete
49
+ connection.http.delete(fedora_identifier(id: id))
48
50
  end
49
51
 
50
52
  class IOProxy
51
53
  # @param response [Ldp::Resource::BinarySource]
52
54
  attr_reader :size
53
- def initialize(source, size)
55
+ def initialize(source)
54
56
  @source = source
55
- @size = size
57
+ @size = source.size
56
58
  end
57
59
  delegate :each, :read, :rewind, to: :io
58
60
 
59
61
  # There is no streaming support in faraday (https://github.com/lostisland/faraday/pull/604)
60
62
  # @return [StringIO]
61
63
  def io
62
- @io ||= StringIO.new(@source.get.response.body)
64
+ @io ||= StringIO.new(@source)
63
65
  end
64
66
  end
65
67
  private_constant :IOProxy
@@ -68,17 +70,24 @@ module Valkyrie::Storage
68
70
 
69
71
  # @return [IOProxy]
70
72
  def response(id:)
71
- af_file = ActiveFedora::File.new(active_fedora_identifier(id: id))
72
- raise Valkyrie::StorageAdapter::FileNotFound if af_file.ldp_source.new?
73
- IOProxy.new(af_file.ldp_source, af_file.size)
73
+ response = connection.http.get(fedora_identifier(id: id))
74
+ raise Valkyrie::StorageAdapter::FileNotFound unless response.success?
75
+ IOProxy.new(response.body)
74
76
  end
75
77
 
76
78
  # Translate the Valkrie ID into a URL for the fedora file
77
79
  # @return [RDF::URI]
78
- def active_fedora_identifier(id:)
79
- scheme = URI(ActiveFedora.config.credentials[:url]).scheme
80
- identifier = id.to_s.sub(PROTOCOL, "#{scheme}://")
80
+ def fedora_identifier(id:)
81
+ identifier = id.to_s.sub(PROTOCOL, "#{connection.http.scheme}://")
81
82
  RDF::URI(identifier)
82
83
  end
84
+
85
+ def id_to_uri(id)
86
+ RDF::URI("#{connection_prefix}/#{CGI.escape(id.to_s)}")
87
+ end
88
+
89
+ def connection_prefix
90
+ "#{connection.http.url_prefix}/#{base_path}"
91
+ end
83
92
  end
84
93
  end
@@ -3,9 +3,11 @@ module Valkyrie
3
3
  # Namespace for Dry::Types types.
4
4
  # Includes Dry::Types built-in types and defines custom Valkyrie types
5
5
  #
6
+ # Types allow your models to automatically cast attributes to the appropriate type
7
+ # or even fail to instantiate should you give an inappropriate type.
8
+ #
6
9
  # @example Use types in property definitions on a resource
7
10
  # class Book < Valkyrie::Resource
8
- # attribute :id, Valkyrie::Types::ID.optional
9
11
  # attribute :title, Valkyrie::Types::Set.optional # default type if none is specified
10
12
  # attribute :member_ids, Valkyrie::Types::Array
11
13
  # end
@@ -38,6 +40,14 @@ module Valkyrie
38
40
  end
39
41
  end
40
42
 
43
+ # Optimistic Lock Token
44
+ OptimisticLockToken =
45
+ Dry::Types::Definition
46
+ .new(::Valkyrie::Persistence::OptimisticLockToken)
47
+ .constructor do |input|
48
+ Valkyrie::Persistence::OptimisticLockToken.deserialize(input)
49
+ end
50
+
41
51
  # Used for casting {Valkyrie::Resources} if possible.
42
52
  Anything = Valkyrie::Types::Any.constructor do |value|
43
53
  if value.respond_to?(:fetch) && value.fetch(:internal_resource, nil)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie
3
- VERSION = "1.1.2"
3
+ VERSION = "1.2.0.rc1"
4
4
  end
data/lib/valkyrie.rb CHANGED
@@ -13,10 +13,8 @@ require 'rdf'
13
13
  require 'valkyrie/rdf_patches'
14
14
  require 'json/ld'
15
15
  require 'logger'
16
- require 'active_triples'
17
16
  require 'rdf/vocab'
18
17
  require 'rails'
19
- require 'active_fedora'
20
18
 
21
19
  module Valkyrie
22
20
  require 'valkyrie/id'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: valkyrie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trey Pendragon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-06-08 00:00:00.000000000 Z
11
+ date: 2018-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-struct
@@ -441,7 +441,6 @@ files:
441
441
  - bin/rspec
442
442
  - bin/setup
443
443
  - browserslist
444
- - config/fedora.yml
445
444
  - config/valkyrie.yml
446
445
  - db/config.yml
447
446
  - db/migrate/20160111215816_enable_uuid_extension.rb
@@ -451,6 +450,7 @@ files:
451
450
  - db/migrate/20171011224121_create_path_gin_index.rb
452
451
  - db/migrate/20171204224121_create_internal_resource_index.rb
453
452
  - db/migrate/20180212092225_create_updated_at_index.rb
453
+ - db/migrate/20180802220739_add_optimistic_locking_to_orm_resources.rb
454
454
  - db/schema.rb
455
455
  - db/seeds.rb
456
456
  - lib/config/database_connection.rb
@@ -485,6 +485,7 @@ files:
485
485
  - lib/valkyrie/persistence/memory/metadata_adapter.rb
486
486
  - lib/valkyrie/persistence/memory/persister.rb
487
487
  - lib/valkyrie/persistence/memory/query_service.rb
488
+ - lib/valkyrie/persistence/optimistic_lock_token.rb
488
489
  - lib/valkyrie/persistence/postgres.rb
489
490
  - lib/valkyrie/persistence/postgres/metadata_adapter.rb
490
491
  - lib/valkyrie/persistence/postgres/orm.rb
@@ -567,12 +568,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
567
568
  version: '0'
568
569
  required_rubygems_version: !ruby/object:Gem::Requirement
569
570
  requirements:
570
- - - ">="
571
+ - - ">"
571
572
  - !ruby/object:Gem::Version
572
- version: '0'
573
+ version: 1.3.1
573
574
  requirements: []
574
575
  rubyforge_project:
575
- rubygems_version: 2.6.14
576
+ rubygems_version: 2.7.7
576
577
  signing_key:
577
578
  specification_version: 4
578
579
  summary: An ORM using the Data Mapper pattern, specifically built to solve Digital
data/config/fedora.yml DELETED
@@ -1,10 +0,0 @@
1
- development:
2
- user: fedoraAdmin
3
- password: fedoraAdmin
4
- url: http://localhost:<%= ENV['FCREPO_DEVELOPMENT_PORT'] || 8986 %>/rest
5
- base_path: /dev
6
- test:
7
- user: fedoraAdmin
8
- password: fedoraAdmin
9
- url: http://localhost:<%= ENV['FCREPO_TEST_PORT'] || 8988 %>/rest
10
- base_path: /test