valkyrie 2.0.0 → 2.1.2
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +60 -56
- data/.lando.yml +40 -0
- data/.rubocop.yml +4 -1
- data/.tool-versions +1 -1
- data/Appraisals +4 -4
- data/CHANGELOG.md +136 -0
- data/README.md +21 -49
- data/Rakefile +21 -20
- data/db/config.yml +3 -10
- data/db/schema.rb +0 -40
- data/gemfiles/activerecord_5_2.gemfile +2 -0
- data/gemfiles/{activerecord_5_1.gemfile → activerecord_6_0.gemfile} +3 -1
- data/lib/generators/valkyrie/resource_generator.rb +3 -3
- data/lib/valkyrie.rb +33 -15
- data/lib/valkyrie/change_set.rb +3 -3
- data/lib/valkyrie/id.rb +26 -3
- data/lib/valkyrie/indexers/access_controls_indexer.rb +17 -17
- data/lib/valkyrie/logging.rb +72 -0
- data/lib/valkyrie/persistence/composite_persister.rb +1 -1
- data/lib/valkyrie/persistence/fedora.rb +2 -0
- data/lib/valkyrie/persistence/fedora/list_node.rb +46 -49
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +2 -2
- data/lib/valkyrie/persistence/fedora/ordered_list.rb +90 -90
- data/lib/valkyrie/persistence/fedora/ordered_reader.rb +5 -5
- data/lib/valkyrie/persistence/fedora/permissive_schema.rb +3 -3
- data/lib/valkyrie/persistence/fedora/persister.rb +82 -83
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +16 -17
- data/lib/valkyrie/persistence/fedora/persister/orm_converter.rb +38 -18
- data/lib/valkyrie/persistence/fedora/query_service.rb +54 -53
- data/lib/valkyrie/persistence/memory/persister.rb +33 -33
- data/lib/valkyrie/persistence/memory/query_service.rb +52 -34
- data/lib/valkyrie/persistence/postgres/orm_converter.rb +52 -52
- data/lib/valkyrie/persistence/postgres/query_service.rb +86 -33
- data/lib/valkyrie/persistence/postgres/resource_converter.rb +1 -1
- data/lib/valkyrie/persistence/shared/json_value_mapper.rb +4 -2
- data/lib/valkyrie/persistence/solr/model_converter.rb +337 -337
- data/lib/valkyrie/persistence/solr/orm_converter.rb +3 -3
- data/lib/valkyrie/persistence/solr/persister.rb +4 -17
- data/lib/valkyrie/persistence/solr/queries/find_all_query.rb +6 -0
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +1 -1
- data/lib/valkyrie/persistence/solr/query_service.rb +42 -53
- data/lib/valkyrie/persistence/solr/repository.rb +2 -1
- data/lib/valkyrie/rdf_patches.rb +2 -2
- data/lib/valkyrie/resource.rb +36 -5
- data/lib/valkyrie/specs/shared_specs/change_set.rb +1 -1
- data/lib/valkyrie/specs/shared_specs/persister.rb +17 -6
- data/lib/valkyrie/specs/shared_specs/queries.rb +112 -9
- data/lib/valkyrie/storage/fedora.rb +17 -17
- data/lib/valkyrie/storage_adapter.rb +16 -13
- data/lib/valkyrie/types.rb +3 -1
- data/lib/valkyrie/version.rb +1 -1
- data/solr/config/solrconfig.xml +0 -10
- data/tasks/dev.rake +14 -51
- data/valkyrie.gemspec +4 -4
- metadata +40 -37
- data/.docker-stack/valkyrie-development/docker-compose.yml +0 -53
- data/.docker-stack/valkyrie-test/docker-compose.yml +0 -53
- data/db/seeds.rb +0 -8
- data/tasks/docker.rake +0 -31
@@ -325,21 +325,21 @@ module Valkyrie::Persistence::Fedora
|
|
325
325
|
class MappedFedoraValue < ::Valkyrie::ValueMapper
|
326
326
|
private
|
327
327
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
328
|
+
# Map a default Ruby data type
|
329
|
+
# (This maps the existing Property to a FedoraValue first)
|
330
|
+
# @param [Object] converted_value
|
331
|
+
# @return [Valkyrie::Persistence::Fedora::Persister::ModelConverter::Property]
|
332
|
+
def map_value(converted_value:)
|
333
|
+
calling_mapper.for(
|
334
|
+
Property.new(
|
335
|
+
value.subject,
|
336
|
+
value.key,
|
337
|
+
converted_value,
|
338
|
+
value.adapter,
|
339
|
+
value.resource
|
340
|
+
)
|
341
|
+
).result
|
342
|
+
end
|
343
343
|
end
|
344
344
|
|
345
345
|
# Class mapping Property objects for Valkyrie IDs using typed RDF literals
|
@@ -488,10 +488,9 @@ module Valkyrie::Persistence::Fedora
|
|
488
488
|
# @return [Valkyrie::Persistence::Fedora::Persister::ModelConverter::Property]
|
489
489
|
def result
|
490
490
|
# cast it to datetime for storage, to preserve milliseconds and date
|
491
|
-
# @todo Remove strftime when https://github.com/ruby-rdf/rdf/issues/394 is closed.
|
492
491
|
map_value(converted_value:
|
493
492
|
RDF::Literal.new(
|
494
|
-
value.value.to_datetime
|
493
|
+
value.value.to_datetime,
|
495
494
|
datatype: PermissiveSchema.valkyrie_time
|
496
495
|
))
|
497
496
|
end
|
@@ -97,11 +97,9 @@ module Valkyrie::Persistence::Fedora
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
# Class for handling cases where
|
101
|
-
class
|
102
|
-
|
103
|
-
|
104
|
-
# Determines whether or not the value has a blacklisted namespace for the RDF statement object
|
100
|
+
# Class for handling cases where deny listed values should not be mapped
|
101
|
+
class DenylistedValue < ::Valkyrie::ValueMapper
|
102
|
+
# Determines whether or not the value has a denied namespace for the RDF statement object
|
105
103
|
# (i. e. avoid attempting to map any RDF statements making assertions about LDP containers or resource internal to Fedora)
|
106
104
|
# @param [Property] value
|
107
105
|
# @return [Boolean]
|
@@ -109,12 +107,20 @@ module Valkyrie::Persistence::Fedora
|
|
109
107
|
value.statement.object.to_s.start_with?("http://www.w3.org/ns/ldp", "http://fedora.info")
|
110
108
|
end
|
111
109
|
|
112
|
-
# Provide the NullApplicator Class for any Property in a
|
110
|
+
# Provide the NullApplicator Class for any Property in a deny listed namespace
|
113
111
|
def result
|
114
112
|
NullApplicator
|
115
113
|
end
|
116
114
|
end
|
117
115
|
|
116
|
+
# @deprecated
|
117
|
+
# Class for handling cases where deny listed values should not be mapped
|
118
|
+
# @see DenylistedValue
|
119
|
+
class BlacklistedValue < DenylistedValue
|
120
|
+
FedoraValue.register(self)
|
121
|
+
warn "[DEPRECATION] Samvera is deprecating '#{self}' in 3.0.0. Use #{DenylistedValue} instead."
|
122
|
+
end
|
123
|
+
|
118
124
|
# Class for handling cases where the RDF subject of a Property references a separate resource using a hash URI
|
119
125
|
class DifferentSubject < ::Valkyrie::ValueMapper
|
120
126
|
FedoraValue.register(self)
|
@@ -318,7 +324,7 @@ module Valkyrie::Persistence::Fedora
|
|
318
324
|
# Casts the value of the RDF literal into an Applicator for DateTime values
|
319
325
|
# @return [Applicator]
|
320
326
|
def result
|
321
|
-
value.statement.object = ::DateTime.iso8601(value.statement.object.to_s).
|
327
|
+
value.statement.object = ::DateTime.iso8601(value.statement.object.to_s).new_offset(0)
|
322
328
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
323
329
|
end
|
324
330
|
end
|
@@ -394,7 +400,7 @@ module Valkyrie::Persistence::Fedora
|
|
394
400
|
# Casts the value of the RDF literal into an Applicator for DateTime values
|
395
401
|
# @return [Applicator]
|
396
402
|
def result
|
397
|
-
value.statement.object =
|
403
|
+
value.statement.object = DateTime.parse(value.statement.object.to_s).new_offset(0)
|
398
404
|
calling_mapper.for(Property.new(statement: value.statement, scope: value.scope, adapter: value.adapter)).result
|
399
405
|
end
|
400
406
|
end
|
@@ -522,7 +528,7 @@ module Valkyrie::Persistence::Fedora
|
|
522
528
|
# @param [Hash] hsh a new or existing Hash of attribute for Valkyrie resource attributes
|
523
529
|
# @return [Hash]
|
524
530
|
def apply_to(hsh)
|
525
|
-
return if
|
531
|
+
return if deny?(key)
|
526
532
|
hsh[key.to_sym] = if hsh.key?(key.to_sym)
|
527
533
|
Array.wrap(hsh[key.to_sym]) + cast_array(values)
|
528
534
|
else
|
@@ -541,13 +547,23 @@ module Valkyrie::Persistence::Fedora
|
|
541
547
|
key
|
542
548
|
end
|
543
549
|
|
544
|
-
#
|
550
|
+
# @deprecated
|
551
|
+
# Determines whether or not a key is on the deny list for mapping
|
545
552
|
# (For example <http://fedora.info/definitions> assertions are not mapped to Valkyrie attributes)
|
546
553
|
# @param [Symbol] key
|
547
554
|
# @return [Boolean]
|
548
555
|
def blacklist?(key)
|
549
|
-
blacklist.
|
550
|
-
|
556
|
+
warn "[DEPRECATION] Samvera is deprecating '#{self.class}#blacklist?' in 3.0.0. Use #{self.class}#deny? instead."
|
557
|
+
deny?(key)
|
558
|
+
end
|
559
|
+
|
560
|
+
# Determines whether or not a key is on the deny list for mapping
|
561
|
+
# (For example <http://fedora.info/definitions> assertions are not mapped to Valkyrie attributes)
|
562
|
+
# @param [Symbol] key
|
563
|
+
# @return [Boolean]
|
564
|
+
def deny?(key)
|
565
|
+
denylist.each do |denylist_item|
|
566
|
+
return true if key.start_with?(denylist_item)
|
551
567
|
end
|
552
568
|
false
|
553
569
|
end
|
@@ -556,16 +572,20 @@ module Valkyrie::Persistence::Fedora
|
|
556
572
|
# @param [Object] values
|
557
573
|
# @return [Array<Object>]
|
558
574
|
def cast_array(values)
|
559
|
-
|
560
|
-
[values]
|
561
|
-
else
|
562
|
-
Array(values)
|
563
|
-
end
|
575
|
+
Array(values)
|
564
576
|
end
|
565
577
|
|
566
|
-
#
|
578
|
+
# @deprecated
|
579
|
+
# Retrieve a list of denied URIs for predicates
|
567
580
|
# @return [Array<String>]
|
568
581
|
def blacklist
|
582
|
+
warn "[DEPRECATION] Samvera is deprecating '#{self.class}#blacklist' in 3.0.0. Use #{self.class}#denylist instead."
|
583
|
+
denylist
|
584
|
+
end
|
585
|
+
|
586
|
+
# Retrieve a list of denied URIs for predicates
|
587
|
+
# @return [Array<String>]
|
588
|
+
def denylist
|
569
589
|
[
|
570
590
|
"http://fedora.info/definitions",
|
571
591
|
"http://www.iana.org/assignments/relation/last"
|
@@ -31,11 +31,9 @@ module Valkyrie::Persistence::Fedora
|
|
31
31
|
def find_many_by_ids(ids:)
|
32
32
|
ids = ids.uniq
|
33
33
|
ids.map do |id|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
nil
|
38
|
-
end
|
34
|
+
find_by(id: id)
|
35
|
+
rescue ::Valkyrie::Persistence::ObjectNotFoundError
|
36
|
+
nil
|
39
37
|
end.reject(&:nil?)
|
40
38
|
end
|
41
39
|
|
@@ -86,11 +84,18 @@ module Valkyrie::Persistence::Fedora
|
|
86
84
|
end
|
87
85
|
end
|
88
86
|
|
87
|
+
# (see Valkyrie::Persistence::Memory::QueryService#count_all_of_model)
|
88
|
+
def count_all_of_model(model:)
|
89
|
+
find_all_of_model(model: model).count
|
90
|
+
end
|
91
|
+
|
89
92
|
# (see Valkyrie::Persistence::Memory::QueryService#find_references_by)
|
90
|
-
def find_references_by(resource:, property:)
|
91
|
-
(resource[property] || []).select { |x| x.is_a?(Valkyrie::ID) }.lazy.map do |id|
|
93
|
+
def find_references_by(resource:, property:, model: nil)
|
94
|
+
objects = (resource[property] || []).select { |x| x.is_a?(Valkyrie::ID) }.lazy.map do |id|
|
92
95
|
find_by(id: id)
|
93
96
|
end
|
97
|
+
return objects unless model
|
98
|
+
objects.select { |obj| obj.is_a?(model) }
|
94
99
|
end
|
95
100
|
|
96
101
|
# Retrieves the RDF graph for the LDP container for a resource
|
@@ -111,15 +116,16 @@ module Valkyrie::Persistence::Fedora
|
|
111
116
|
# Find all resources referencing a given resource (e. g. parents)
|
112
117
|
# *This is done by iterating through the ID of each resource referencing the resource in the query, and requesting each resource over the HTTP*
|
113
118
|
# *Also, an initial request is made to find the URIs of the resources referencing the resource in the query*
|
114
|
-
def find_inverse_references_by(resource: nil, id: nil, property:)
|
119
|
+
def find_inverse_references_by(resource: nil, id: nil, property:, model: nil)
|
115
120
|
raise ArgumentError, "Provide resource or id" unless resource || id
|
116
121
|
ensure_persisted(resource) if resource
|
117
122
|
resource ||= find_by(id: id)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
+
ids = find_inverse_reference_ids_by_unordered(resource: resource, property: property).uniq
|
124
|
+
objects_from_unordered = ids.lazy.map { |ref_id| find_by(id: ref_id) }
|
125
|
+
objects_from_ordered = find_inverse_references_by_ordered(resource: resource, property: property, ignore_ids: ids)
|
126
|
+
objects = [objects_from_unordered, objects_from_ordered].lazy.flat_map(&:lazy)
|
127
|
+
return objects unless model
|
128
|
+
objects.select { |obj| obj.is_a?(model) }
|
123
129
|
end
|
124
130
|
|
125
131
|
# (see Valkyrie::Persistence::Memory::QueryService#custom_queries)
|
@@ -129,49 +135,44 @@ module Valkyrie::Persistence::Fedora
|
|
129
135
|
|
130
136
|
private
|
131
137
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
ids.lazy.map { |id| find_by(id: id) }
|
138
|
-
end
|
139
|
-
|
140
|
-
def find_inverse_references_by_ordered(resource:, property:)
|
141
|
-
content = content_with_inbound(id: resource.id)
|
142
|
-
ids = content.graph.query([nil, ::RDF::Vocab::ORE.proxyFor, adapter.id_to_uri(resource.id)]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
|
143
|
-
ids.uniq!
|
144
|
-
ids.lazy.map { |id| find_by(id: id) }.select { |o| o[property].include?(resource.id) }
|
145
|
-
end
|
138
|
+
def find_inverse_reference_ids_by_unordered(resource:, property:)
|
139
|
+
content = content_with_inbound(id: resource.id)
|
140
|
+
property_uri = adapter.schema.predicate_for(property: property, resource: nil)
|
141
|
+
content.graph.query([nil, property_uri, adapter.id_to_uri(resource.id)]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
|
142
|
+
end
|
146
143
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
144
|
+
def find_inverse_references_by_ordered(resource:, property:, ignore_ids: [])
|
145
|
+
content = content_with_inbound(id: resource.id)
|
146
|
+
ids = content.graph.query([nil, ::RDF::Vocab::ORE.proxyFor, adapter.id_to_uri(resource.id)]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
|
147
|
+
ids.uniq!
|
148
|
+
ids.delete_if { |id| ignore_ids.include? id }
|
149
|
+
ids.lazy.map { |id| find_by(id: id) }.select { |o| o[property].include?(resource.id) }
|
150
|
+
end
|
154
151
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
rescue ::Ldp::Gone, ::Ldp::NotFound
|
163
|
-
raise ::Valkyrie::Persistence::ObjectNotFoundError
|
164
|
-
end
|
152
|
+
# Ensures that an object is (or can be cast into a) Valkyrie::ID
|
153
|
+
# @return [Valkyrie::ID]
|
154
|
+
# @raise [ArgumentError]
|
155
|
+
def validate_id(id)
|
156
|
+
id = Valkyrie::ID.new(id.to_s) if id.is_a?(String)
|
157
|
+
raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
|
158
|
+
end
|
165
159
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
160
|
+
# Resolve a URI for an LDP resource in Fedora and construct a Valkyrie::Resource
|
161
|
+
# @param uri [RDF::URI]
|
162
|
+
# @return [Valkyrie::Resource]
|
163
|
+
# @raise [Valkyrie::Persistence::ObjectNotFoundError]
|
164
|
+
def resource_from_uri(uri)
|
165
|
+
resource = Ldp::Resource.for(connection, uri, connection.get(uri))
|
166
|
+
resource_factory.to_resource(object: resource)
|
167
|
+
rescue ::Ldp::Gone, ::Ldp::NotFound
|
168
|
+
raise ::Valkyrie::Persistence::ObjectNotFoundError
|
169
|
+
end
|
172
170
|
|
173
|
-
|
174
|
-
|
175
|
-
|
171
|
+
# Ensures that a Valkyrie::Resource has been persisted
|
172
|
+
# @param resource [Valkyrie::Resource]
|
173
|
+
# @raise [ArgumentError]
|
174
|
+
def ensure_persisted(resource)
|
175
|
+
raise ArgumentError, 'resource is not saved' unless resource.persisted?
|
176
|
+
end
|
176
177
|
end
|
177
178
|
end
|
@@ -62,46 +62,46 @@ module Valkyrie::Persistence::Memory
|
|
62
62
|
|
63
63
|
private
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
def generate_id(resource)
|
66
|
+
resource.new(id: SecureRandom.uuid)
|
67
|
+
end
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
# Convert all dates to DateTime in the UTC time zone for consistency.
|
70
|
+
def normalize_dates!(resource)
|
71
|
+
resource.attributes.each { |k, v| resource.send("#{k}=", normalize_date_values(v)) }
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
74
|
+
def normalize_date_values(v)
|
75
|
+
return v.map { |val| normalize_date_value(val) } if v.is_a?(Array)
|
76
|
+
normalize_date_value(v)
|
77
|
+
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
def normalize_date_value(value)
|
80
|
+
return value.new_offset(0) if value.is_a?(DateTime)
|
81
|
+
return value.to_datetime.new_offset(0) if value.is_a?(Time)
|
82
|
+
value
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
85
|
+
# Create a new lock token based on the current timestamp.
|
86
|
+
def generate_lock_token(resource)
|
87
|
+
return unless resource.optimistic_locking_enabled?
|
88
|
+
token = Valkyrie::Persistence::OptimisticLockToken.new(adapter_id: adapter.id, token: Time.now.to_r)
|
89
|
+
resource.set_value(Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK, token)
|
90
|
+
end
|
91
91
|
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
# Check whether a resource is current.
|
93
|
+
def valid_lock?(resource)
|
94
|
+
return true unless resource.optimistic_locking_enabled?
|
95
95
|
|
96
|
-
|
97
|
-
|
96
|
+
cached_resource = cache[resource.id]
|
97
|
+
return true if cached_resource.blank?
|
98
98
|
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
resource_lock_tokens = resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK]
|
100
|
+
resource_value = resource_lock_tokens.find { |lock_token| lock_token.adapter_id == adapter.id }
|
101
|
+
return true if resource_value.blank?
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
cached_value = cached_resource[Valkyrie::Persistence::Attributes::OPTIMISTIC_LOCK].first
|
104
|
+
cached_value == resource_value
|
105
|
+
end
|
106
106
|
end
|
107
107
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Valkyrie::Persistence::Memory
|
3
|
+
# Query Service for the memory metadata adapter.
|
4
|
+
# @see Valkyrie::Persistence::Memory
|
5
|
+
# @note Documentation for Query Services in general is maintained here.
|
3
6
|
class QueryService
|
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
7
|
attr_reader :adapter, :query_handlers
|
8
8
|
delegate :cache, to: :adapter
|
9
9
|
|
@@ -27,7 +27,9 @@ module Valkyrie::Persistence::Memory
|
|
27
27
|
cache[id] || raise(::Valkyrie::Persistence::ObjectNotFoundError)
|
28
28
|
end
|
29
29
|
|
30
|
-
# Get a single resource by `alternate_identifier`.
|
30
|
+
# Get a single resource by `alternate_identifier`. Alternate identifiers are identifiers (like NOIDs,
|
31
|
+
# DOIs, ARKs, etc.) that are not the system-generated ID, but might be used to identify a resource in an
|
32
|
+
# application (e.g., to make shorter URLs).
|
31
33
|
# @param alternate_identifier [Valkyrie::ID] The alternate identifier to query for.
|
32
34
|
# @raise [Valkyrie::Persistence::ObjectNotFoundError] Raised when the alternate identifier
|
33
35
|
# isn't in the persistence backend.
|
@@ -49,11 +51,9 @@ module Valkyrie::Persistence::Memory
|
|
49
51
|
def find_many_by_ids(ids:)
|
50
52
|
ids = ids.uniq
|
51
53
|
ids.map do |id|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
nil
|
56
|
-
end
|
54
|
+
find_by(id: id)
|
55
|
+
rescue ::Valkyrie::Persistence::ObjectNotFoundError
|
56
|
+
nil
|
57
57
|
end.reject(&:nil?)
|
58
58
|
end
|
59
59
|
|
@@ -73,9 +73,17 @@ module Valkyrie::Persistence::Memory
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
# Count all objects of a given model.
|
77
|
+
# @param model [Class] Class to query for.
|
78
|
+
# @return integer. Count objects in the persistence backend
|
79
|
+
# with the given class.
|
80
|
+
def count_all_of_model(model:)
|
81
|
+
cache.values.count { |obj| obj.is_a?(model) }
|
82
|
+
end
|
83
|
+
|
76
84
|
# Get all members of a given resource.
|
77
85
|
# @param resource [Valkyrie::Resource] Model whose members are being searched for.
|
78
|
-
# @param model [Class]
|
86
|
+
# @param model [Class] Filter results to include only instances of this model. (optional)
|
79
87
|
# @return [Array<Valkyrie::Resource>] child objects of type `model` referenced by
|
80
88
|
# `resource`'s `member_ids` method. Returned in order.
|
81
89
|
def find_members(resource:, model: nil)
|
@@ -90,36 +98,41 @@ module Valkyrie::Persistence::Memory
|
|
90
98
|
# @param resource [Valkyrie::Resource] Model whose property is being searched.
|
91
99
|
# @param property [Symbol] Property which, on the `resource`, contains {Valkyrie::ID}s which are
|
92
100
|
# to be de-referenced.
|
101
|
+
# @param model [Class] Filter results to include only instances of this model. (optional)
|
93
102
|
# @return [Array<Valkyrie::Resource>] All objects which are referenced by the
|
94
103
|
# `property` property on `resource`. Not necessarily in order.
|
95
|
-
def find_references_by(resource:, property:)
|
104
|
+
def find_references_by(resource:, property:, model: nil)
|
96
105
|
refs = Array.wrap(resource[property]).map do |id|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
nil
|
101
|
-
end
|
106
|
+
find_by(id: id)
|
107
|
+
rescue ::Valkyrie::Persistence::ObjectNotFoundError
|
108
|
+
nil
|
102
109
|
end.reject(&:nil?)
|
103
110
|
refs.uniq! unless ordered_property?(resource: resource, property: property)
|
104
|
-
refs
|
111
|
+
return refs unless model
|
112
|
+
refs.select { |obj| obj.is_a?(model) }
|
105
113
|
end
|
106
114
|
|
107
115
|
# Get all resources which link to a resource with a given property.
|
108
116
|
# @param resource [Valkyrie::Resource] The resource which is being referenced by
|
109
|
-
# other resources.
|
117
|
+
# other resources. Requires either resource or id parameter to be specified.
|
118
|
+
# @param id [Valkyrie::ID] ID of the resource which is being reference by other
|
119
|
+
# resources. Requires either resource or id parameter to be specified.
|
110
120
|
# @param property [Symbol] The property which, on other resources, is
|
111
121
|
# referencing the given `resource`
|
122
|
+
# @param model [Class] Filter results to include only instances of this model. (optional)
|
112
123
|
# @raise [ArgumentError] Raised when the ID is not in the persistence backend.
|
113
124
|
# @return [Array<Valkyrie::Resource>] All resources in the persistence backend
|
114
125
|
# which have the ID of the given `resource` in their `property` property. Not
|
115
126
|
# in order.
|
116
|
-
def find_inverse_references_by(resource: nil, id: nil, property:)
|
127
|
+
def find_inverse_references_by(resource: nil, id: nil, property:, model: nil)
|
117
128
|
raise ArgumentError, "Provide resource or id" unless resource || id
|
118
129
|
ensure_persisted(resource) if resource
|
119
130
|
id ||= resource.id
|
120
|
-
find_all.select do |obj|
|
131
|
+
result = find_all.select do |obj|
|
121
132
|
Array.wrap(obj[property]).include?(id)
|
122
133
|
end
|
134
|
+
return result unless model
|
135
|
+
result.select { |obj| obj.is_a?(model) }
|
123
136
|
end
|
124
137
|
|
125
138
|
# Find all parents of a given resource.
|
@@ -142,22 +155,27 @@ module Valkyrie::Persistence::Memory
|
|
142
155
|
|
143
156
|
private
|
144
157
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
158
|
+
# @return [Array<Valkyrie::ID>] a list of the identifiers of the member objects
|
159
|
+
def member_ids(resource:)
|
160
|
+
return [] unless resource.respond_to? :member_ids
|
161
|
+
resource.member_ids || []
|
162
|
+
end
|
150
163
|
|
151
|
-
|
152
|
-
|
153
|
-
|
164
|
+
# Determine whether or not a value is a Valkyrie ID
|
165
|
+
# @param [Object] id
|
166
|
+
# @return [Boolean]
|
167
|
+
def validate_id(id)
|
168
|
+
raise ArgumentError, 'id must be a Valkyrie::ID' unless id.is_a? Valkyrie::ID
|
169
|
+
end
|
154
170
|
|
155
|
-
|
156
|
-
|
157
|
-
|
171
|
+
# Ensure that a given Valkyrie Resource has been persisted
|
172
|
+
# @param [Valkyrie::Resource] resource
|
173
|
+
def ensure_persisted(resource)
|
174
|
+
raise ArgumentError, 'resource is not saved' unless resource.persisted?
|
175
|
+
end
|
158
176
|
|
159
|
-
|
160
|
-
|
161
|
-
|
177
|
+
def ordered_property?(resource:, property:)
|
178
|
+
resource.ordered_attribute?(property)
|
179
|
+
end
|
162
180
|
end
|
163
181
|
end
|