valkyrie 1.2.1 → 1.2.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 +5 -5
- data/.rubocop_todo.yml +1 -0
- data/CHANGELOG.md +7 -0
- data/lib/valkyrie.rb +29 -2
- data/lib/valkyrie/persistence/fedora/metadata_adapter.rb +5 -0
- data/lib/valkyrie/persistence/fedora/persister/model_converter.rb +9 -1
- data/lib/valkyrie/persistence/fedora/query_service.rb +25 -5
- data/lib/valkyrie/persistence/memory/metadata_adapter.rb +5 -0
- data/lib/valkyrie/persistence/memory/query_service.rb +14 -3
- data/lib/valkyrie/persistence/postgres/metadata_adapter.rb +7 -1
- data/lib/valkyrie/persistence/postgres/query_service.rb +4 -3
- data/lib/valkyrie/persistence/solr/metadata_adapter.rb +7 -1
- data/lib/valkyrie/persistence/solr/queries/find_members_query.rb +13 -6
- data/lib/valkyrie/persistence/solr/queries/find_ordered_references_query.rb +2 -2
- data/lib/valkyrie/persistence/solr/query_service.rb +10 -3
- data/lib/valkyrie/specs/shared_specs/queries.rb +86 -20
- data/lib/valkyrie/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f665fe8da6906565cf3773a62c028e0528d62074c50fd109bbd6dd438196f4fb
|
4
|
+
data.tar.gz: f0db72ec609cfa390a1cdaef4e03d8dd0834c25e51cbac8845a061dda7458281
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 797105358eece5769534d6c62cfd6599d1d3ceeb66e36b0a9ded3750f266fae69d57ec0e8929cc33b579066e7ecad862a249510c1fac551093723cfdbe66a711
|
7
|
+
data.tar.gz: 96ac6d47efa9dc4d00235ac4e0ffb00a63141f13ab89bc622bc0a7bd6161200df7622e6e03419840b3ae003a3f53b045ca8e33737c72ddd00e419e66927aafc0
|
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/lib/valkyrie.rb
CHANGED
@@ -34,10 +34,20 @@ module Valkyrie
|
|
34
34
|
require 'valkyrie/engine' if defined?(Rails)
|
35
35
|
def config
|
36
36
|
@config ||= Config.new(
|
37
|
-
|
37
|
+
config_hash
|
38
38
|
)
|
39
39
|
end
|
40
40
|
|
41
|
+
def config_file
|
42
|
+
return unless File.exist?(config_root_path.join("config", "valkyrie.yml"))
|
43
|
+
File.read(config_root_path.join("config", "valkyrie.yml"))
|
44
|
+
end
|
45
|
+
|
46
|
+
def config_hash
|
47
|
+
return {} unless config_file
|
48
|
+
YAML.safe_load(ERB.new(config_file).result)[environment]
|
49
|
+
end
|
50
|
+
|
41
51
|
def environment
|
42
52
|
Rails.env
|
43
53
|
end
|
@@ -58,7 +68,16 @@ module Valkyrie
|
|
58
68
|
@logger = logger
|
59
69
|
end
|
60
70
|
|
71
|
+
def warn_about_standard_queries!
|
72
|
+
warn "[DEPRECATION] Please enable query normalization to avoid inconsistent results between different adapters by adding `standardize_query_results: true` to your environment block" \
|
73
|
+
" in config\/valkyrie.yml. This will be the behavior in Valkyrie 2.0."
|
74
|
+
end
|
75
|
+
|
61
76
|
class Config < OpenStruct
|
77
|
+
def initialize(hsh = {})
|
78
|
+
super(defaults.merge(hsh))
|
79
|
+
end
|
80
|
+
|
62
81
|
def metadata_adapter
|
63
82
|
Valkyrie::MetadataAdapter.find(super.to_sym)
|
64
83
|
end
|
@@ -66,7 +85,15 @@ module Valkyrie
|
|
66
85
|
def storage_adapter
|
67
86
|
Valkyrie::StorageAdapter.find(super.to_sym)
|
68
87
|
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def defaults
|
92
|
+
{
|
93
|
+
standardize_query_result: false
|
94
|
+
}
|
95
|
+
end
|
69
96
|
end
|
70
97
|
|
71
|
-
module_function :config, :logger, :logger=, :config_root_path, :environment
|
98
|
+
module_function :config, :logger, :logger=, :config_root_path, :environment, :warn_about_standard_queries!, :config_file, :config_hash
|
72
99
|
end
|
@@ -73,5 +73,10 @@ module Valkyrie::Persistence::Fedora
|
|
73
73
|
def connection_prefix
|
74
74
|
"#{connection.http.url_prefix}/#{base_path}"
|
75
75
|
end
|
76
|
+
|
77
|
+
def standardize_query_result?
|
78
|
+
Valkyrie.warn_about_standard_queries! if Valkyrie.config.standardize_query_result != true
|
79
|
+
Valkyrie.config.standardize_query_result == true
|
80
|
+
end
|
76
81
|
end
|
77
82
|
end
|
@@ -238,7 +238,7 @@ module Valkyrie::Persistence::Fedora
|
|
238
238
|
obj = calling_mapper.for(property.property).result
|
239
239
|
# Append value directly if possible.
|
240
240
|
if obj.respond_to?(:value)
|
241
|
-
ordered_list.insert_proxy_for_at(index, obj.value)
|
241
|
+
ordered_list.insert_proxy_for_at(index, proxy_for_value(obj.value))
|
242
242
|
# If value is a nested object, take its graph and append it.
|
243
243
|
elsif obj.respond_to?(:graph)
|
244
244
|
append_to_graph(obj: obj, index: index, property: property.property)
|
@@ -247,6 +247,14 @@ module Valkyrie::Persistence::Fedora
|
|
247
247
|
end
|
248
248
|
end
|
249
249
|
|
250
|
+
def proxy_for_value(value)
|
251
|
+
if value.is_a?(RDF::Literal) && value.datatype == PermissiveSchema.valkyrie_id
|
252
|
+
ordered_list.adapter.id_to_uri(value)
|
253
|
+
else
|
254
|
+
value
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
250
258
|
class NestedProperty
|
251
259
|
attr_reader :value, :scope
|
252
260
|
def initialize(value:, scope:)
|
@@ -29,6 +29,7 @@ module Valkyrie::Persistence::Fedora
|
|
29
29
|
|
30
30
|
# (see Valkyrie::Persistence::Memory::QueryService#find_many_by_ids)
|
31
31
|
def find_many_by_ids(ids:)
|
32
|
+
ids = ids.uniq if adapter.standardize_query_result?
|
32
33
|
ids.map do |id|
|
33
34
|
begin
|
34
35
|
find_by(id: id)
|
@@ -42,6 +43,7 @@ module Valkyrie::Persistence::Fedora
|
|
42
43
|
def find_parents(resource:)
|
43
44
|
content = content_with_inbound(id: resource.id)
|
44
45
|
parent_ids = content.graph.query([nil, RDF::Vocab::ORE.proxyFor, nil]).map(&:subject).map { |x| x.to_s.gsub(/#.*/, '') }.map { |x| adapter.uri_to_id(x) }
|
46
|
+
parent_ids.uniq! if adapter.standardize_query_result?
|
45
47
|
parent_ids.lazy.map do |id|
|
46
48
|
find_by(id: id)
|
47
49
|
end
|
@@ -111,11 +113,10 @@ module Valkyrie::Persistence::Fedora
|
|
111
113
|
# *Also, an initial request is made to find the URIs of the resources referencing the resource in the query*
|
112
114
|
def find_inverse_references_by(resource:, property:)
|
113
115
|
ensure_persisted(resource)
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
find_by(id: id)
|
116
|
+
if ordered_property?(resource: resource, property: property)
|
117
|
+
find_inverse_references_by_ordered(resource: resource, property: property)
|
118
|
+
else
|
119
|
+
find_inverse_references_by_unordered(resource: resource, property: property)
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
@@ -126,6 +127,21 @@ module Valkyrie::Persistence::Fedora
|
|
126
127
|
|
127
128
|
private
|
128
129
|
|
130
|
+
def find_inverse_references_by_unordered(resource:, property:)
|
131
|
+
content = content_with_inbound(id: resource.id)
|
132
|
+
property_uri = adapter.schema.predicate_for(property: property, resource: nil)
|
133
|
+
ids = 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) }
|
134
|
+
ids.uniq! if adapter.standardize_query_result?
|
135
|
+
ids.lazy.map { |id| find_by(id: id) }
|
136
|
+
end
|
137
|
+
|
138
|
+
def find_inverse_references_by_ordered(resource:, property:)
|
139
|
+
content = content_with_inbound(id: resource.id)
|
140
|
+
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) }
|
141
|
+
ids.uniq! if adapter.standardize_query_result?
|
142
|
+
ids.lazy.map { |id| find_by(id: id) }.select { |o| o[property].include?(resource.id) }
|
143
|
+
end
|
144
|
+
|
129
145
|
# Ensures that an object is (or can be cast into a) Valkyrie::ID
|
130
146
|
# @return [Valkyrie::ID]
|
131
147
|
# @raise [ArgumentError]
|
@@ -151,5 +167,9 @@ module Valkyrie::Persistence::Fedora
|
|
151
167
|
def ensure_persisted(resource)
|
152
168
|
raise ArgumentError, 'resource is not saved' unless resource.persisted?
|
153
169
|
end
|
170
|
+
|
171
|
+
def ordered_property?(resource:, property:)
|
172
|
+
resource.class.schema[property].meta.try(:[], :ordered)
|
173
|
+
end
|
154
174
|
end
|
155
175
|
end
|
@@ -29,5 +29,10 @@ module Valkyrie::Persistence::Memory
|
|
29
29
|
def id
|
30
30
|
@id ||= Valkyrie::ID.new(Digest::MD5.hexdigest(self.class.to_s))
|
31
31
|
end
|
32
|
+
|
33
|
+
def standardize_query_result?
|
34
|
+
Valkyrie.warn_about_standard_queries! if Valkyrie.config.standardize_query_result != true
|
35
|
+
Valkyrie.config.standardize_query_result == true
|
36
|
+
end
|
32
37
|
end
|
33
38
|
end
|
@@ -44,6 +44,7 @@ module Valkyrie::Persistence::Memory
|
|
44
44
|
# @raise [ArgumentError] Raised when any ID is not a String or a Valkyrie::ID
|
45
45
|
# @return [Array<Valkyrie::Resource>] All requested objects that were found
|
46
46
|
def find_many_by_ids(ids:)
|
47
|
+
ids = ids.uniq if adapter.standardize_query_result?
|
47
48
|
ids.map do |id|
|
48
49
|
begin
|
49
50
|
find_by(id: id)
|
@@ -89,9 +90,15 @@ module Valkyrie::Persistence::Memory
|
|
89
90
|
# @return [Array<Valkyrie::Resource>] All objects which are referenced by the
|
90
91
|
# `property` property on `resource`. Not necessarily in order.
|
91
92
|
def find_references_by(resource:, property:)
|
92
|
-
Array.wrap(resource[property]).map do |id|
|
93
|
-
|
94
|
-
|
93
|
+
refs = Array.wrap(resource[property]).map do |id|
|
94
|
+
begin
|
95
|
+
find_by(id: id)
|
96
|
+
rescue ::Valkyrie::Persistence::ObjectNotFoundError
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
end.reject(&:nil?)
|
100
|
+
refs.uniq! if adapter.standardize_query_result? && !ordered_property?(resource: resource, property: property)
|
101
|
+
refs
|
95
102
|
end
|
96
103
|
|
97
104
|
# Get all resources which link to a resource with a given property.
|
@@ -147,5 +154,9 @@ module Valkyrie::Persistence::Memory
|
|
147
154
|
def ensure_persisted(resource)
|
148
155
|
raise ArgumentError, 'resource is not saved' unless resource.persisted?
|
149
156
|
end
|
157
|
+
|
158
|
+
def ordered_property?(resource:, property:)
|
159
|
+
resource.class.schema[property].meta.try(:[], :ordered)
|
160
|
+
end
|
150
161
|
end
|
151
162
|
end
|
@@ -17,7 +17,8 @@ module Valkyrie::Persistence::Postgres
|
|
17
17
|
# @return [Class] {Valkyrie::Persistence::Postgres::QueryService}
|
18
18
|
def query_service
|
19
19
|
@query_service ||= Valkyrie::Persistence::Postgres::QueryService.new(
|
20
|
-
resource_factory: resource_factory
|
20
|
+
resource_factory: resource_factory,
|
21
|
+
adapter: self
|
21
22
|
)
|
22
23
|
end
|
23
24
|
|
@@ -34,5 +35,10 @@ module Valkyrie::Persistence::Postgres
|
|
34
35
|
Valkyrie::ID.new(Digest::MD5.hexdigest(to_hash))
|
35
36
|
end
|
36
37
|
end
|
38
|
+
|
39
|
+
def standardize_query_result?
|
40
|
+
Valkyrie.warn_about_standard_queries! if Valkyrie.config.standardize_query_result != true
|
41
|
+
Valkyrie.config.standardize_query_result == true
|
42
|
+
end
|
37
43
|
end
|
38
44
|
end
|
@@ -7,12 +7,13 @@ module Valkyrie::Persistence::Postgres
|
|
7
7
|
#
|
8
8
|
# @see Valkyrie::Persistence::Postgres::MetadataAdapter
|
9
9
|
class QueryService
|
10
|
-
attr_reader :resource_factory
|
10
|
+
attr_reader :resource_factory, :adapter
|
11
11
|
delegate :orm_class, to: :resource_factory
|
12
12
|
|
13
13
|
# @param [ResourceFactory] resource_factory
|
14
|
-
def initialize(resource_factory:)
|
14
|
+
def initialize(adapter:, resource_factory:)
|
15
15
|
@resource_factory = resource_factory
|
16
|
+
@adapter = adapter
|
16
17
|
end
|
17
18
|
|
18
19
|
# Retrieve all records for the resource and construct Valkyrie Resources
|
@@ -188,7 +189,7 @@ module Valkyrie::Persistence::Postgres
|
|
188
189
|
# @return [String]
|
189
190
|
def find_references_query
|
190
191
|
<<-SQL
|
191
|
-
SELECT member.* FROM orm_resources a,
|
192
|
+
SELECT #{adapter.standardize_query_result? ? 'DISTINCT' : ''} member.* FROM orm_resources a,
|
192
193
|
jsonb_array_elements(a.metadata->?) AS b(member)
|
193
194
|
JOIN orm_resources member ON (b.member->>'id')::#{id_type} = member.id WHERE a.id = ?
|
194
195
|
SQL
|
@@ -46,7 +46,8 @@ module Valkyrie::Persistence::Solr
|
|
46
46
|
def query_service
|
47
47
|
@query_service ||= Valkyrie::Persistence::Solr::QueryService.new(
|
48
48
|
connection: connection,
|
49
|
-
resource_factory: resource_factory
|
49
|
+
resource_factory: resource_factory,
|
50
|
+
adapter: self
|
50
51
|
)
|
51
52
|
end
|
52
53
|
|
@@ -63,6 +64,11 @@ module Valkyrie::Persistence::Solr
|
|
63
64
|
Valkyrie::Persistence::Solr::ResourceFactory.new(resource_indexer: resource_indexer, adapter: self)
|
64
65
|
end
|
65
66
|
|
67
|
+
def standardize_query_result?
|
68
|
+
Valkyrie.warn_about_standard_queries! if Valkyrie.config.standardize_query_result != true
|
69
|
+
Valkyrie.config.standardize_query_result == true
|
70
|
+
end
|
71
|
+
|
66
72
|
# Class modeling the indexer for cases where indexing is *not* performed
|
67
73
|
class NullIndexer
|
68
74
|
# @note this is a no-op
|
@@ -3,17 +3,18 @@ module Valkyrie::Persistence::Solr::Queries
|
|
3
3
|
# Responsible for returning all members of a given resource as
|
4
4
|
# {Valkyrie::Resource}s
|
5
5
|
class FindMembersQuery
|
6
|
-
attr_reader :resource, :connection, :resource_factory, :model
|
6
|
+
attr_reader :resource, :connection, :resource_factory, :model, :standardize_query_result
|
7
7
|
|
8
8
|
# @param [Valkyrie::Resource] resource
|
9
9
|
# @param [RSolr::Client] connection
|
10
10
|
# @param [ResourceFactory] resource_factory
|
11
11
|
# @param [Class] model
|
12
|
-
def initialize(resource:, connection:, resource_factory:, model:)
|
12
|
+
def initialize(resource:, connection:, resource_factory:, model:, standardize_query_result:)
|
13
13
|
@resource = resource
|
14
14
|
@connection = connection
|
15
15
|
@resource_factory = resource_factory
|
16
16
|
@model = model
|
17
|
+
@standardize_query_result = standardize_query_result
|
17
18
|
end
|
18
19
|
|
19
20
|
# Iterate over each Solr Document and convert each Document into a Valkyrie Resource
|
@@ -28,15 +29,21 @@ module Valkyrie::Persistence::Solr::Queries
|
|
28
29
|
# @yield [Valkyrie::Resource]
|
29
30
|
def each
|
30
31
|
return [] unless resource.id.present?
|
31
|
-
|
32
|
-
|
32
|
+
if standardize_query_result
|
33
|
+
member_ids.map { |id| unordered_members.find { |member| member.id == id } }.reject(&:nil?).each do |member|
|
34
|
+
yield member
|
35
|
+
end
|
36
|
+
else
|
37
|
+
unordered_members.sort_by { |x| member_ids.index(x.id) }.each do |member|
|
38
|
+
yield member
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
43
|
# Retrieving the Solr Documents for the member resources, construct Valkyrie Resources for each
|
37
44
|
# @return [Array<Valkyrie::Resource>]
|
38
45
|
def unordered_members
|
39
|
-
docs.map do |doc|
|
46
|
+
@unordered_members ||= docs.map do |doc|
|
40
47
|
resource_factory.to_resource(object: doc)
|
41
48
|
end
|
42
49
|
end
|
@@ -55,7 +62,7 @@ module Valkyrie::Persistence::Solr::Queries
|
|
55
62
|
# Access the IDs of the members for the Valkyrie Resource
|
56
63
|
# @return [Array<Valkyrie::ID>]
|
57
64
|
def member_ids
|
58
|
-
Array.wrap(resource.member_ids)
|
65
|
+
resource.respond_to?(:member_ids) ? Array.wrap(resource.member_ids) : []
|
59
66
|
end
|
60
67
|
|
61
68
|
# Generate the Solr join query using the id_ssi field
|
@@ -17,13 +17,13 @@ module Valkyrie::Persistence::Solr::Queries
|
|
17
17
|
|
18
18
|
def each
|
19
19
|
# map them off of the property to fix solr's deduplication
|
20
|
-
property_values.map { |id| unordered_members.find { |member| member.id == id } } .each do |value|
|
20
|
+
property_values.map { |id| unordered_members.find { |member| member.id == id } } .reject(&:nil?).each do |value|
|
21
21
|
yield value
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
25
|
def unordered_members
|
26
|
-
docs.map do |doc|
|
26
|
+
@unordered_members ||= docs.map do |doc|
|
27
27
|
resource_factory.to_resource(object: doc)
|
28
28
|
end
|
29
29
|
end
|
@@ -3,12 +3,13 @@ module Valkyrie::Persistence::Solr
|
|
3
3
|
require 'valkyrie/persistence/solr/queries'
|
4
4
|
# Query Service for Solr MetadataAdapter.
|
5
5
|
class QueryService
|
6
|
-
attr_reader :connection, :resource_factory
|
6
|
+
attr_reader :connection, :resource_factory, :adapter
|
7
7
|
# @param [RSolr::Client] connection
|
8
8
|
# @param [Valkyrie::Persistence::Solr::ResourceFactory] resource_factory
|
9
|
-
def initialize(connection:, resource_factory:)
|
9
|
+
def initialize(connection:, resource_factory:, adapter:)
|
10
10
|
@connection = connection
|
11
11
|
@resource_factory = resource_factory
|
12
|
+
@adapter = adapter
|
12
13
|
end
|
13
14
|
|
14
15
|
# Find resources by Valkyrie ID
|
@@ -65,7 +66,13 @@ module Valkyrie::Persistence::Solr
|
|
65
66
|
# @param [Valkyrie::Resource] parent resource
|
66
67
|
# @return [Array<Valkyrie::Resource>] member resources
|
67
68
|
def find_members(resource:, model: nil)
|
68
|
-
Valkyrie::Persistence::Solr::Queries::FindMembersQuery.new(
|
69
|
+
Valkyrie::Persistence::Solr::Queries::FindMembersQuery.new(
|
70
|
+
resource: resource,
|
71
|
+
model: model,
|
72
|
+
connection: connection,
|
73
|
+
resource_factory: resource_factory,
|
74
|
+
standardize_query_result: adapter.standardize_query_result?
|
75
|
+
).run
|
69
76
|
end
|
70
77
|
|
71
78
|
# Find all of the resources referenced by a given Valkyrie Resource using a specific property
|
@@ -7,7 +7,7 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
7
7
|
attribute :alternate_ids, Valkyrie::Types::Array
|
8
8
|
attribute :title
|
9
9
|
attribute :member_ids, Valkyrie::Types::Array
|
10
|
-
attribute :a_member_of
|
10
|
+
attribute :a_member_of, Valkyrie::Types::Array
|
11
11
|
attribute :an_ordered_member_of, Valkyrie::Types::Array.meta(ordered: true)
|
12
12
|
end
|
13
13
|
class SecondResource < Valkyrie::Resource
|
@@ -22,6 +22,8 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
22
22
|
let(:persister) { adapter.persister }
|
23
23
|
subject { adapter.query_service }
|
24
24
|
|
25
|
+
before { allow(Valkyrie.config).to receive(:standardize_query_result).and_return(true) }
|
26
|
+
|
25
27
|
it { is_expected.to respond_to(:find_all).with(0).arguments }
|
26
28
|
it { is_expected.to respond_to(:find_all_of_model).with_keywords(:model) }
|
27
29
|
it { is_expected.to respond_to(:find_by).with_keywords(:id) }
|
@@ -139,6 +141,11 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
139
141
|
it 'raises an error if any id is not a Valkyrie::ID or a string' do
|
140
142
|
expect { query_service.find_many_by_ids(ids: [resource.id, 123]) }.to raise_error ArgumentError
|
141
143
|
end
|
144
|
+
|
145
|
+
it "removes duplicates" do
|
146
|
+
found = query_service.find_many_by_ids(ids: [resource.id, resource2.id, resource.id])
|
147
|
+
expect(found.map(&:id)).to contain_exactly resource.id, resource2.id
|
148
|
+
end
|
142
149
|
end
|
143
150
|
|
144
151
|
describe ".find_members" do
|
@@ -153,6 +160,13 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
153
160
|
it "returns all a resource's members in order" do
|
154
161
|
expect(subject.map(&:id).to_a).to eq [child2.id, child1.id]
|
155
162
|
end
|
163
|
+
|
164
|
+
context "when something is member more than once" do
|
165
|
+
let(:parent) { persister.save(resource: resource_class.new(member_ids: [child1.id, child2.id, child1.id])) }
|
166
|
+
it "includes duplicates" do
|
167
|
+
expect(subject.map(&:id).to_a).to eq [child1.id, child2.id, child1.id]
|
168
|
+
end
|
169
|
+
end
|
156
170
|
end
|
157
171
|
|
158
172
|
context "when there's no resource ID" do
|
@@ -207,20 +221,39 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
207
221
|
end
|
208
222
|
|
209
223
|
describe ".find_references_by" do
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
224
|
+
context "when the property is unordered" do
|
225
|
+
it "returns all references given in a property" do
|
226
|
+
parent = persister.save(resource: resource_class.new)
|
227
|
+
parent2 = persister.save(resource: resource_class.new)
|
228
|
+
child = persister.save(resource: resource_class.new(a_member_of: [parent.id, parent2.id]))
|
229
|
+
persister.save(resource: resource_class.new)
|
214
230
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
231
|
+
expect(query_service.find_references_by(resource: child, property: :a_member_of).map(&:id).to_a).to contain_exactly parent.id, parent2.id
|
232
|
+
end
|
233
|
+
|
234
|
+
it "returns an empty array if there are none" do
|
235
|
+
child = persister.save(resource: resource_class.new)
|
236
|
+
expect(query_service.find_references_by(resource: child, property: :a_member_of).to_a).to eq []
|
237
|
+
end
|
238
|
+
|
239
|
+
it "removes duplicates" do
|
240
|
+
parent = persister.save(resource: resource_class.new)
|
241
|
+
child = persister.save(resource: resource_class.new(a_member_of: [parent.id, parent.id]))
|
242
|
+
persister.save(resource: resource_class.new)
|
243
|
+
|
244
|
+
expect(query_service.find_references_by(resource: child, property: :a_member_of).map(&:id).to_a).to contain_exactly parent.id
|
245
|
+
end
|
246
|
+
|
247
|
+
it "returns nothing if reference not found" do
|
248
|
+
child = persister.save(resource: resource_class.new(a_member_of: ["123123123"]))
|
249
|
+
persister.save(resource: resource_class.new)
|
250
|
+
|
251
|
+
expect(query_service.find_references_by(resource: child, property: :a_member_of).map(&:id).to_a).to eq []
|
252
|
+
end
|
220
253
|
end
|
221
254
|
|
222
255
|
context "when the property is ordered" do
|
223
|
-
it "returns all references in order" do
|
256
|
+
it "returns all references in order including duplicates" do
|
224
257
|
parent = persister.save(resource: resource_class.new)
|
225
258
|
parent2 = persister.save(resource: resource_class.new)
|
226
259
|
child = persister.save(resource: resource_class.new(an_ordered_member_of: [parent.id, parent2.id, parent.id]))
|
@@ -228,23 +261,47 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
228
261
|
|
229
262
|
expect(query_service.find_references_by(resource: child, property: :an_ordered_member_of).map(&:id).to_a).to eq [parent.id, parent2.id, parent.id]
|
230
263
|
end
|
264
|
+
|
265
|
+
it "returns nothing if reference not found" do
|
266
|
+
child = persister.save(resource: resource_class.new(an_ordered_member_of: ["123123123"]))
|
267
|
+
persister.save(resource: resource_class.new)
|
268
|
+
|
269
|
+
expect(query_service.find_references_by(resource: child, property: :an_ordered_member_of).map(&:id).to_a).to eq []
|
270
|
+
end
|
231
271
|
end
|
232
272
|
end
|
233
273
|
|
234
274
|
describe ".find_inverse_references_by" do
|
235
275
|
context "when the resource is saved" do
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
276
|
+
context "when the property is unordered" do
|
277
|
+
it "returns everything which references the given resource by the given property" do
|
278
|
+
parent = persister.save(resource: resource_class.new)
|
279
|
+
parent2 = persister.save(resource: resource_class.new)
|
280
|
+
child = persister.save(resource: resource_class.new(a_member_of: [parent.id]))
|
281
|
+
child2 = persister.save(resource: resource_class.new(a_member_of: [parent.id, parent2.id, parent.id]))
|
282
|
+
persister.save(resource: resource_class.new)
|
283
|
+
persister.save(resource: SecondResource.new)
|
284
|
+
|
285
|
+
expect(query_service.find_inverse_references_by(resource: parent, property: :a_member_of).map(&:id).to_a).to contain_exactly child.id, child2.id
|
286
|
+
end
|
241
287
|
|
242
|
-
|
288
|
+
it "returns an empty array if there are none" do
|
289
|
+
parent = persister.save(resource: resource_class.new)
|
290
|
+
|
291
|
+
expect(query_service.find_inverse_references_by(resource: parent, property: :a_member_of).to_a).to eq []
|
292
|
+
end
|
243
293
|
end
|
244
|
-
it "returns an empty array if there are none" do
|
245
|
-
parent = persister.save(resource: resource_class.new)
|
246
294
|
|
247
|
-
|
295
|
+
context "when the property is ordered" do
|
296
|
+
it "returns everything which references the given resource by the given property" do
|
297
|
+
parent = persister.save(resource: resource_class.new)
|
298
|
+
child = persister.save(resource: resource_class.new(an_ordered_member_of: [parent.id]))
|
299
|
+
child2 = persister.save(resource: resource_class.new(an_ordered_member_of: [parent.id, parent.id]))
|
300
|
+
persister.save(resource: resource_class.new)
|
301
|
+
persister.save(resource: SecondResource.new)
|
302
|
+
|
303
|
+
expect(query_service.find_inverse_references_by(resource: parent, property: :an_ordered_member_of).map(&:id).to_a).to contain_exactly child.id, child2.id
|
304
|
+
end
|
248
305
|
end
|
249
306
|
end
|
250
307
|
context "when the resource is not saved" do
|
@@ -265,12 +322,21 @@ RSpec.shared_examples 'a Valkyrie query provider' do
|
|
265
322
|
|
266
323
|
expect(query_service.find_parents(resource: child1).map(&:id).to_a).to contain_exactly parent.id, parent2.id
|
267
324
|
end
|
325
|
+
|
268
326
|
it "returns an empty array if there are none" do
|
269
327
|
child1 = persister.save(resource: resource_class.new)
|
270
328
|
|
271
329
|
expect(query_service.find_parents(resource: child1).to_a).to eq []
|
272
330
|
end
|
273
331
|
|
332
|
+
it "doesn't return same parent twice" do
|
333
|
+
child1 = persister.save(resource: resource_class.new)
|
334
|
+
parent = persister.save(resource: resource_class.new(member_ids: [child1.id, child1.id]))
|
335
|
+
parent2 = persister.save(resource: resource_class.new(member_ids: [child1.id]))
|
336
|
+
|
337
|
+
expect(query_service.find_parents(resource: child1).map(&:id).to_a).to contain_exactly parent.id, parent2.id
|
338
|
+
end
|
339
|
+
|
274
340
|
context "when the model doesn't have member_ids" do
|
275
341
|
let(:child1) { persister.save(resource: SecondResource.new) }
|
276
342
|
|
data/lib/valkyrie/version.rb
CHANGED
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.2.
|
4
|
+
version: 1.2.2
|
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-
|
11
|
+
date: 2018-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dry-struct
|
@@ -589,7 +589,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
589
589
|
version: '0'
|
590
590
|
requirements: []
|
591
591
|
rubyforge_project:
|
592
|
-
rubygems_version: 2.
|
592
|
+
rubygems_version: 2.7.7
|
593
593
|
signing_key:
|
594
594
|
specification_version: 4
|
595
595
|
summary: An ORM using the Data Mapper pattern, specifically built to solve Digital
|