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