valkyrie 0.1.0 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +5 -5
  2. data/.ctags +2 -0
  3. data/.rubocop.yml +5 -0
  4. data/.rubocop_todo.yml +3 -0
  5. data/CHANGELOG.md +43 -0
  6. data/Gemfile +0 -4
  7. data/LICENSE +15 -0
  8. data/README.md +13 -8
  9. data/Rakefile +15 -1
  10. data/bin/jetty_wait +14 -0
  11. data/bin/rspec +29 -0
  12. data/browserslist +3 -0
  13. data/circle.yml +17 -0
  14. data/config/fedora.yml +10 -0
  15. data/db/migrate/20161007101725_create_orm_resources.rb +9 -1
  16. data/db/migrate/20171011224121_create_path_gin_index.rb +6 -0
  17. data/db/migrate/20171204224121_create_internal_resource_index.rb +6 -0
  18. data/db/migrate/20180212092225_create_updated_at_index.rb +6 -0
  19. data/lib/generators/valkyrie/templates/resource_spec.rb.erb +1 -1
  20. data/lib/valkyrie.rb +1 -7
  21. data/lib/valkyrie/change_set.rb +21 -7
  22. data/lib/valkyrie/engine.rb +2 -0
  23. data/lib/valkyrie/id.rb +1 -0
  24. data/lib/valkyrie/indexers/access_controls_indexer.rb +50 -6
  25. data/lib/valkyrie/metadata_adapter.rb +29 -1
  26. data/lib/valkyrie/persistence.rb +27 -0
  27. data/lib/valkyrie/persistence/buffered_persister.rb +17 -1
  28. data/lib/valkyrie/persistence/composite_persister.rb +14 -2
  29. data/lib/valkyrie/persistence/custom_query_container.rb +63 -0
  30. data/lib/valkyrie/persistence/delete_tracking_buffer.rb +8 -0
  31. data/lib/valkyrie/persistence/fedora.rb +3 -0
  32. data/lib/valkyrie/persistence/fedora/list_node.rb +5 -2
  33. data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +13 -11
  34. data/lib/valkyrie/persistence/fedora/ordered_list.rb +2 -2
  35. data/lib/valkyrie/persistence/fedora/ordered_reader.rb +3 -2
  36. data/lib/valkyrie/persistence/fedora/permissive_schema.rb +75 -0
  37. data/lib/valkyrie/persistence/fedora/persister.rb +22 -0
  38. data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +110 -25
  39. data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +49 -17
  40. data/lib/valkyrie/persistence/fedora/persister/resource_factory.rb +2 -0
  41. data/lib/valkyrie/persistence/fedora/query_service.rb +46 -3
  42. data/lib/valkyrie/persistence/memory.rb +5 -0
  43. data/lib/valkyrie/persistence/memory/metadata_adapter.rb +6 -1
  44. data/lib/valkyrie/persistence/memory/persister.rb +19 -1
  45. data/lib/valkyrie/persistence/memory/query_service.rb +49 -8
  46. data/lib/valkyrie/persistence/postgres.rb +2 -0
  47. data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +8 -1
  48. data/lib/valkyrie/persistence/postgres/orm.rb +1 -0
  49. data/lib/valkyrie/persistence/postgres/orm/resource.rb +12 -0
  50. data/lib/valkyrie/persistence/postgres/orm_converter.rb +99 -74
  51. data/lib/valkyrie/persistence/postgres/persister.rb +16 -0
  52. data/lib/valkyrie/persistence/postgres/query_service.rb +94 -6
  53. data/lib/valkyrie/persistence/postgres/resource_converter.rb +3 -1
  54. data/lib/valkyrie/persistence/postgres/resource_factory.rb +5 -5
  55. data/lib/valkyrie/persistence/solr.rb +2 -0
  56. data/lib/valkyrie/persistence/solr/composite_indexer.rb +29 -0
  57. data/lib/valkyrie/persistence/solr/metadata_adapter.rb +26 -1
  58. data/lib/valkyrie/persistence/solr/model_converter.rb +38 -8
  59. data/lib/valkyrie/persistence/solr/orm_converter.rb +43 -20
  60. data/lib/valkyrie/persistence/solr/persister.rb +16 -0
  61. data/lib/valkyrie/persistence/solr/queries.rb +3 -0
  62. data/lib/valkyrie/persistence/solr/queries/default_paginator.rb +2 -0
  63. data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +3 -1
  64. data/lib/valkyrie/persistence/solr/queries/find_by_id_query.rb +4 -2
  65. data/lib/valkyrie/persistence/solr/queries/find_inverse_references_query.rb +2 -0
  66. data/lib/valkyrie/persistence/solr/queries/find_many_by_ids_query.rb +21 -0
  67. data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +13 -5
  68. data/lib/valkyrie/persistence/solr/queries/find_references_query.rb +7 -3
  69. data/lib/valkyrie/persistence/solr/query_service.rb +30 -2
  70. data/lib/valkyrie/persistence/solr/repository.rb +14 -2
  71. data/lib/valkyrie/persistence/solr/resource_factory.rb +3 -1
  72. data/lib/valkyrie/resource.rb +11 -4
  73. data/lib/valkyrie/resource/access_controls.rb +13 -0
  74. data/lib/valkyrie/specs/shared_specs.rb +1 -2
  75. data/lib/valkyrie/specs/shared_specs/change_set.rb +75 -0
  76. data/lib/valkyrie/specs/shared_specs/metadata_adapter.rb +3 -0
  77. data/lib/valkyrie/specs/shared_specs/persister.rb +145 -15
  78. data/lib/valkyrie/specs/shared_specs/queries.rb +153 -27
  79. data/lib/valkyrie/specs/shared_specs/storage_adapter.rb +8 -3
  80. data/lib/valkyrie/storage.rb +29 -0
  81. data/lib/valkyrie/storage/disk.rb +17 -5
  82. data/lib/valkyrie/storage/fedora.rb +14 -1
  83. data/lib/valkyrie/storage/memory.rb +15 -2
  84. data/lib/valkyrie/storage_adapter.rb +26 -4
  85. data/lib/valkyrie/types.rb +65 -7
  86. data/lib/valkyrie/version.rb +1 -1
  87. data/solr/config/_rest_managed.json +3 -0
  88. data/solr/config/admin-extra.html +31 -0
  89. data/solr/config/elevate.xml +36 -0
  90. data/solr/config/mapping-ISOLatin1Accent.txt +246 -0
  91. data/solr/config/protwords.txt +21 -0
  92. data/solr/config/schema.xml +366 -0
  93. data/solr/config/scripts.conf +24 -0
  94. data/solr/config/solrconfig.xml +322 -0
  95. data/solr/config/spellings.txt +2 -0
  96. data/solr/config/stopwords.txt +58 -0
  97. data/solr/config/stopwords_en.txt +58 -0
  98. data/solr/config/synonyms.txt +31 -0
  99. data/solr/config/xslt/example.xsl +132 -0
  100. data/solr/config/xslt/example_atom.xsl +67 -0
  101. data/solr/config/xslt/example_rss.xsl +66 -0
  102. data/solr/config/xslt/luke.xsl +337 -0
  103. data/solr/solr.xml +35 -0
  104. data/tasks/dev.rake +66 -0
  105. data/valkyrie.gemspec +6 -6
  106. metadata +58 -63
  107. data/lib/valkyrie/decorators/decorator_list.rb +0 -15
  108. data/lib/valkyrie/decorators/decorator_with_arguments.rb +0 -14
  109. data/lib/valkyrie/derivative_service.rb +0 -42
  110. data/lib/valkyrie/file_characterization_service.rb +0 -42
  111. data/lib/valkyrie/local_file_service.rb +0 -11
  112. data/lib/valkyrie/persist_derivatives.rb +0 -29
  113. data/lib/valkyrie/persistence/postgres/queries.rb +0 -8
  114. data/lib/valkyrie/persistence/postgres/queries/find_inverse_references_query.rb +0 -31
  115. data/lib/valkyrie/persistence/postgres/queries/find_members_query.rb +0 -33
  116. data/lib/valkyrie/persistence/postgres/queries/find_references_query.rb +0 -33
  117. data/lib/valkyrie/specs/shared_specs/derivative_service.rb +0 -30
  118. data/lib/valkyrie/specs/shared_specs/file_characterization_service.rb +0 -33
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
+ #
2
3
  module Valkyrie::Persistence
4
+ # Implements the DataMapper Pattern to store metadata in memory
5
+ #
6
+ # @note this adapter is used primarily for testing, and is not recommended
7
+ # in cases where you want to preserve real data
3
8
  module Memory
4
9
  require 'valkyrie/persistence/memory/metadata_adapter'
5
10
  require 'valkyrie/persistence/memory/persister'
@@ -1,5 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Memory
3
+ # MetadataAdapter for the memory adapter.
4
+ # @see Valkyrie::Persistence::Memory
5
+ # @note Documentation for instance methods on other MetadataAdapters are
6
+ # copied from the Memory implementation via `(see
7
+ # Valkyrie::Persistence::Memory#method)` to reduce duplication.
3
8
  class MetadataAdapter
4
9
  attr_writer :cache
5
10
 
@@ -12,7 +17,7 @@ module Valkyrie::Persistence::Memory
12
17
  # @return [Valkyrie::Persistence::Memory::QueryService] A query service for
13
18
  # this adapter.
14
19
  def query_service
15
- Valkyrie::Persistence::Memory::QueryService.new(adapter: self)
20
+ @query_service ||= Valkyrie::Persistence::Memory::QueryService.new(adapter: self)
16
21
  end
17
22
 
18
23
  def cache
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Memory
3
+ # Persister for the memory metadata adapter.
4
+ # @see Valkyrie::Persistence::Memory
5
+ # @note Documentation for persisters in general is maintained here.
3
6
  class Persister
4
7
  attr_reader :adapter
5
8
  delegate :cache, to: :adapter
@@ -14,8 +17,11 @@ module Valkyrie::Persistence::Memory
14
17
  # persistence backend.
15
18
  def save(resource:)
16
19
  resource = generate_id(resource) if resource.id.blank?
20
+ resource.created_at ||= Time.current
17
21
  resource.updated_at = Time.current
22
+ resource.new_record = false
18
23
  normalize_dates!(resource)
24
+ ensure_multiple_values!(resource)
19
25
  cache[resource.id] = resource
20
26
  end
21
27
 
@@ -34,10 +40,22 @@ module Valkyrie::Persistence::Memory
34
40
  cache.delete(resource.id)
35
41
  end
36
42
 
43
+ # Wipes all data in the persistence backend.
44
+ def wipe!
45
+ cache.clear
46
+ end
47
+
37
48
  private
38
49
 
39
50
  def generate_id(resource)
40
- resource.new(id: SecureRandom.uuid, created_at: Time.current)
51
+ resource.new(id: SecureRandom.uuid)
52
+ end
53
+
54
+ def ensure_multiple_values!(resource)
55
+ bad_keys = resource.attributes.except(:internal_resource, :created_at, :updated_at, :new_record, :id).select do |_k, v|
56
+ !v.nil? && !v.is_a?(Array)
57
+ end
58
+ raise ::Valkyrie::Persistence::UnsupportedDatatype, "#{resource}: #{bad_keys.keys} have non-array values, which can not be persisted by Valkyrie. Cast to arrays." unless bad_keys.keys.empty?
41
59
  end
42
60
 
43
61
  def normalize_dates!(resource)
@@ -1,28 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Memory
3
3
  class QueryService
4
- attr_reader :adapter
4
+ # Query Service for the memory metadata adapter.
5
+ # @see Valkyrie::Persistence::Memory
6
+ # @note Documentation for Query Services in general is maintained here.
7
+ attr_reader :adapter, :query_handlers
5
8
  delegate :cache, to: :adapter
6
9
  # @param adapter [Valkyrie::Persistence::Memory::MetadataAdapter] The adapter which
7
10
  # has the cache to query.
8
11
  def initialize(adapter:)
9
12
  @adapter = adapter
13
+ @query_handlers = []
10
14
  end
11
15
 
12
16
  # @param id [Valkyrie::ID] The ID to query for.
13
17
  # @raise [Valkyrie::Persistence::ObjectNotFoundError] Raised when the ID
14
18
  # isn't in the persistence backend.
19
+ # @raise [ArgumentError] Raised when ID is not a String or a Valkyrie::ID
15
20
  # @return [Valkyrie::Resource] The object being searched for.
16
21
  def find_by(id:)
22
+ id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
23
+ validate_id(id)
17
24
  cache[id] || raise(::Valkyrie::Persistence::ObjectNotFoundError)
18
25
  end
19
26
 
27
+ # @param ids [Array<Valkyrie::ID, String>] The IDs to query for.
28
+ # @raise [ArgumentError] Raised when any ID is not a String or a Valkyrie::ID
29
+ # @return [Array<Valkyrie::Resource>] All requested objects that were found
30
+ def find_many_by_ids(ids:)
31
+ ids.map do |id|
32
+ begin
33
+ find_by(id: id)
34
+ rescue ::Valkyrie::Persistence::ObjectNotFoundError
35
+ nil
36
+ end
37
+ end.reject(&:nil?)
38
+ end
39
+
20
40
  # @return [Array<Valkyrie::Resource>] All objects in the persistence backend.
21
41
  def find_all
22
42
  cache.values
23
43
  end
24
44
 
25
- # @param resource [Class] Class to query for.
45
+ # @param model [Class] Class to query for.
26
46
  # @return [Array<Valkyrie::Resource>] All objects in the persistence backend
27
47
  # with the given class.
28
48
  def find_all_of_model(model:)
@@ -32,12 +52,15 @@ module Valkyrie::Persistence::Memory
32
52
  end
33
53
 
34
54
  # @param resource [Valkyrie::Resource] Model whose members are being searched for.
35
- # @return [Array<Valkyrie::Resource>] All child objects referenced by `resource`'s
36
- # `member_ids` method. Returned in order.
37
- def find_members(resource:)
38
- member_ids(resource: resource).map do |id|
55
+ # @param model [Class] Class to query for. (optional)
56
+ # @return [Array<Valkyrie::Resource>] child objects of type `model` referenced by
57
+ # `resource`'s `member_ids` method. Returned in order.
58
+ def find_members(resource:, model: nil)
59
+ result = member_ids(resource: resource).map do |id|
39
60
  find_by(id: id)
40
61
  end
62
+ return result unless model
63
+ result.select { |obj| obj.is_a?(model) }
41
64
  end
42
65
 
43
66
  # @param resource [Valkyrie::Resource] Model whose property is being searched.
@@ -55,10 +78,12 @@ module Valkyrie::Persistence::Memory
55
78
  # other resources.
56
79
  # @param property [Symbol] The property which, on other resources, is
57
80
  # referencing the given `resource`
81
+ # @raise [ArgumentError] Raised when the ID is not in the persistence backend.
58
82
  # @return [Array<Valkyrie::Resource>] All resources in the persistence backend
59
83
  # which have the ID of the given `resource` in their `property` property. Not
60
84
  # in order.
61
85
  def find_inverse_references_by(resource:, property:)
86
+ ensure_persisted(resource)
62
87
  find_all.select do |obj|
63
88
  begin
64
89
  Array.wrap(obj[property]).include?(resource.id)
@@ -79,8 +104,24 @@ module Valkyrie::Persistence::Memory
79
104
  end
80
105
  end
81
106
 
82
- def member_ids(resource:)
83
- resource.member_ids || []
107
+ def custom_queries
108
+ @custom_queries ||= ::Valkyrie::Persistence::CustomQueryContainer.new(query_service: self)
84
109
  end
110
+
111
+ private
112
+
113
+ # @return [Array<Valkyrie::ID>] a list of the identifiers of the member objects
114
+ def member_ids(resource:)
115
+ return [] unless resource.respond_to? :member_ids
116
+ resource.member_ids || []
117
+ end
118
+
119
+ def validate_id(id)
120
+ raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
121
+ end
122
+
123
+ def ensure_persisted(resource)
124
+ raise ArgumentError, 'resource is not saved' unless resource.persisted?
125
+ end
85
126
  end
86
127
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
+ #
2
3
  module Valkyrie::Persistence
4
+ # Implements the DataMapper Pattern to store metadata into Postgres
3
5
  module Postgres
4
6
  require 'valkyrie/persistence/postgres/metadata_adapter'
5
7
  end
@@ -2,6 +2,12 @@
2
2
  require 'valkyrie/persistence/postgres/persister'
3
3
  require 'valkyrie/persistence/postgres/query_service'
4
4
  module Valkyrie::Persistence::Postgres
5
+ # Metadata Adapter for Postgres Adapter.
6
+ #
7
+ # This adapter uses ActiveRecord to persist resources in a JSON-B column named
8
+ # `metadata`. This requires setting up a database.
9
+ #
10
+ # @see https://github.com/samvera-labs/valkyrie/wiki/Set-up-Valkyrie-database-in-a-Rails-Application
5
11
  class MetadataAdapter
6
12
  # @return [Class] {Valkyrie::Persistence::Postgres::Persister}
7
13
  def persister
@@ -10,9 +16,10 @@ module Valkyrie::Persistence::Postgres
10
16
 
11
17
  # @return [Class] {Valkyrie::Persistence::Postgres::QueryService}
12
18
  def query_service
13
- Valkyrie::Persistence::Postgres::QueryService.new(adapter: self)
19
+ @query_service ||= Valkyrie::Persistence::Postgres::QueryService.new(adapter: self)
14
20
  end
15
21
 
22
+ # @return [Class] {Valkyrie::Persistence::Postgres::ResourceFactory}
16
23
  def resource_factory
17
24
  Valkyrie::Persistence::Postgres::ResourceFactory
18
25
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require 'valkyrie/persistence/postgres/orm/resource'
3
3
  module Valkyrie::Persistence::Postgres
4
+ # Namespace for ActiveRecord access in Postgres adapter.
4
5
  module ORM
5
6
  def self.table_name_prefix
6
7
  'orm_'
@@ -1,6 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Postgres
3
3
  module ORM
4
+ # ActiveRecord class which the Postgres adapter uses for persisting data.
5
+ # @!attribute id
6
+ # @return [UUID] ID of the record
7
+ # @!attribute metadata
8
+ # @return [Hash] Hash of all metadata.
9
+ # @!attribute created_at
10
+ # @return [DateTime] Date created
11
+ # @!attribute updated_at
12
+ # @return [DateTime] Date updated
13
+ # @!attribute internal_resource
14
+ # @return [String] Name of {Valkyrie::Resource} model - used for casting.
15
+ #
4
16
  class Resource < ActiveRecord::Base
5
17
  end
6
18
  end
@@ -1,118 +1,143 @@
1
1
  # frozen_string_literal: true
2
2
  module Valkyrie::Persistence::Postgres
3
+ # Responsible for converting a
4
+ # {Valkyrie::Persistence::Postgres::ORM::Resource} to a {Valkyrie::Resource}
3
5
  class ORMConverter
4
6
  attr_reader :orm_object
5
7
  def initialize(orm_object)
6
8
  @orm_object = orm_object
7
9
  end
8
10
 
11
+ # Create a new instance of the class described in attributes[:internal_resource]
12
+ # and send it all the attributes that @orm_object has
9
13
  def convert!
10
- @resource ||= attributes[:internal_resource].constantize.new(attributes)
14
+ @resource ||= resource
11
15
  end
12
16
 
13
- # @return [Hash] Valkyrie-style hash of attributes.
14
- def attributes
15
- @attributes ||= orm_object.attributes.merge(rdf_metadata).symbolize_keys
16
- end
17
+ private
17
18
 
18
- def rdf_metadata
19
- @rdf_metadata ||= RDFMetadata.new(orm_object.metadata).result
20
- end
19
+ def resource
20
+ resource_klass.new(attributes.merge(new_record: false))
21
+ end
21
22
 
22
- class RDFMetadata
23
- attr_reader :metadata
24
- def initialize(metadata)
25
- @metadata = metadata
23
+ def resource_klass
24
+ internal_resource.constantize
26
25
  end
27
26
 
28
- def result
29
- Hash[
30
- metadata.map do |key, value|
31
- [key, PostgresValue.for(value).result]
32
- end
33
- ]
27
+ def internal_resource
28
+ attributes[:internal_resource]
34
29
  end
35
30
 
36
- class PostgresValue < ::Valkyrie::ValueMapper
31
+ # @return [Hash] Valkyrie-style hash of attributes.
32
+ def attributes
33
+ @attributes ||= orm_object.attributes.merge(rdf_metadata).symbolize_keys
37
34
  end
38
- # Converts {RDF::Literal} typed-literals from JSON-LD stored into an
39
- # {RDF::Literal}
40
- class HashValue < ::Valkyrie::ValueMapper
41
- PostgresValue.register(self)
42
- def self.handles?(value)
43
- value.is_a?(Hash) && value["@value"]
44
- end
45
35
 
46
- def result
47
- RDF::Literal.new(value["@value"], language: value["@language"])
48
- end
36
+ def rdf_metadata
37
+ @rdf_metadata ||= RDFMetadata.new(orm_object.metadata).result
49
38
  end
50
39
 
51
- # Converts stored IDs into {Valkyrie::ID}s
52
- class IDValue < ::Valkyrie::ValueMapper
53
- PostgresValue.register(self)
54
- def self.handles?(value)
55
- value.is_a?(Hash) && value["id"] && !value["internal_resource"]
40
+ # Responsible for converting `metadata` JSON-B field in
41
+ # {Valkyrie::Persistence::Postgres::ORM::Resource} into an acceptable hash
42
+ # for {Valkyrie::Resource}
43
+ class RDFMetadata
44
+ attr_reader :metadata
45
+ def initialize(metadata)
46
+ @metadata = metadata
56
47
  end
57
48
 
58
49
  def result
59
- Valkyrie::ID.new(value["id"])
50
+ Hash[
51
+ metadata.map do |key, value|
52
+ [key, PostgresValue.for(value).result]
53
+ end
54
+ ]
60
55
  end
61
- end
62
56
 
63
- # Converts stored URIs into {RDF::URI}s
64
- class URIValue < ::Valkyrie::ValueMapper
65
- PostgresValue.register(self)
66
- def self.handles?(value)
67
- value.is_a?(Hash) && value["@id"]
57
+ class PostgresValue < ::Valkyrie::ValueMapper
68
58
  end
59
+ # Converts {RDF::Literal} typed-literals from JSON-LD stored into an
60
+ # {RDF::Literal}
61
+ class HashValue < ::Valkyrie::ValueMapper
62
+ PostgresValue.register(self)
63
+ def self.handles?(value)
64
+ value.is_a?(Hash) && value["@value"]
65
+ end
69
66
 
70
- def result
71
- ::RDF::URI.new(value["@id"])
67
+ def result
68
+ RDF::Literal.new(value["@value"],
69
+ language: value["@language"],
70
+ datatype: value["@type"])
71
+ end
72
72
  end
73
- end
74
73
 
75
- # Converts nested records into {Valkyrie::Resource}s
76
- class NestedRecord < ::Valkyrie::ValueMapper
77
- PostgresValue.register(self)
78
- def self.handles?(value)
79
- value.is_a?(Hash) && value.keys.length > 1
80
- end
74
+ # Converts stored IDs into {Valkyrie::ID}s
75
+ class IDValue < ::Valkyrie::ValueMapper
76
+ PostgresValue.register(self)
77
+ def self.handles?(value)
78
+ value.is_a?(Hash) && value["id"] && !value["internal_resource"]
79
+ end
81
80
 
82
- def result
83
- RDFMetadata.new(value).result.symbolize_keys
81
+ def result
82
+ Valkyrie::ID.new(value["id"])
83
+ end
84
84
  end
85
- end
86
85
 
87
- class DateValue < ::Valkyrie::ValueMapper
88
- PostgresValue.register(self)
89
- def self.handles?(value)
90
- return false unless value.is_a?(String)
91
- return false unless value[4] == "-"
92
- year = value.to_s[0..3]
93
- return false unless year.length == 4 && year.to_i.to_s == year
94
- DateTime.iso8601(value)
95
- rescue
96
- false
86
+ # Converts stored URIs into {RDF::URI}s
87
+ class URIValue < ::Valkyrie::ValueMapper
88
+ PostgresValue.register(self)
89
+ def self.handles?(value)
90
+ value.is_a?(Hash) && value["@id"]
91
+ end
92
+
93
+ def result
94
+ ::RDF::URI.new(value["@id"])
95
+ end
97
96
  end
98
97
 
99
- def result
100
- DateTime.iso8601(value).utc
98
+ # Converts nested records into {Valkyrie::Resource}s
99
+ class NestedRecord < ::Valkyrie::ValueMapper
100
+ PostgresValue.register(self)
101
+ def self.handles?(value)
102
+ value.is_a?(Hash) && value.keys.length > 1
103
+ end
104
+
105
+ def result
106
+ RDFMetadata.new(value).result.symbolize_keys
107
+ end
101
108
  end
102
- end
103
109
 
104
- class EnumeratorValue < ::Valkyrie::ValueMapper
105
- PostgresValue.register(self)
106
- def self.handles?(value)
107
- value.respond_to?(:each)
110
+ # Converts Date strings to `DateTime`
111
+ class DateValue < ::Valkyrie::ValueMapper
112
+ PostgresValue.register(self)
113
+ def self.handles?(value)
114
+ return false unless value.is_a?(String)
115
+ return false unless value[4] == "-"
116
+ year = value.to_s[0..3]
117
+ return false unless year.length == 4 && year.to_i.to_s == year
118
+ DateTime.iso8601(value)
119
+ rescue
120
+ false
121
+ end
122
+
123
+ def result
124
+ DateTime.iso8601(value).utc
125
+ end
108
126
  end
109
127
 
110
- def result
111
- value.map do |value|
112
- calling_mapper.for(value).result
128
+ # Handles iterating over arrays of values and converting each value.
129
+ class EnumeratorValue < ::Valkyrie::ValueMapper
130
+ PostgresValue.register(self)
131
+ def self.handles?(value)
132
+ value.respond_to?(:each)
133
+ end
134
+
135
+ def result
136
+ value.map do |value|
137
+ calling_mapper.for(value).result
138
+ end
113
139
  end
114
140
  end
115
141
  end
116
- end
117
142
  end
118
143
  end