speedy-af 0.4.0 → 0.5.0
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 +8 -0
- data/README.md +6 -0
- data/docker-compose.yml +26 -0
- data/lib/speedy_af/base.rb +50 -23
- data/lib/speedy_af/version.rb +1 -1
- data/spec/fixture_classes.rb +28 -5
- data/spec/integration/base_spec.rb +91 -12
- metadata +4 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0ff0f3d554f80151433f700cfae02d61d3c271fbcfb1cefe132d8a9e0e518734
|
4
|
+
data.tar.gz: 01433ba5beca3308fa708191c76a2be9df2b5682be1ae41a3dc08f6ad6dd42af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09e918cd65f5a0ee8a1cf5365f268f68fb265c39da957265598cfd8fa1c363ce5447b0523b7e938264505f49ac420e80af38c331390fb8c547eb5621a519e3d8'
|
7
|
+
data.tar.gz: e900999b19accf9c9d35c8b33480bfdd32b79375c34bd9d8108bfaf92105d67984aafdcb2b8196906d91ccb3aa7357ae5f8de373b1162898406fca6e8f378c1a
|
data/.circleci/config.yml
CHANGED
@@ -37,6 +37,14 @@ jobs:
|
|
37
37
|
workflows:
|
38
38
|
ci:
|
39
39
|
jobs:
|
40
|
+
- bundle_and_test:
|
41
|
+
name: "ruby3-4_rails8-0"
|
42
|
+
ruby_version: "3.4.5"
|
43
|
+
rails_version: "8.0.1"
|
44
|
+
- bundle_and_test:
|
45
|
+
name: "ruby3-3_rails8-0"
|
46
|
+
ruby_version: "3.3.4"
|
47
|
+
rails_version: "8.0.1"
|
40
48
|
- bundle_and_test:
|
41
49
|
name: "ruby3-3_rails7-2"
|
42
50
|
ruby_version: "3.3.4"
|
data/README.md
CHANGED
@@ -91,6 +91,12 @@ If you have questions or need help, please email [the Hydra community tech list]
|
|
91
91
|
be more mindful of both local resources and Solr request limits.
|
92
92
|
* `Base` may not play nicely with language-tagged RDF literals, as ActiveFedora does not
|
93
93
|
currently index/encode the language tag into Solr.
|
94
|
+
* belongs_to relationships do not respect `include_reflections` filtering and will fetch all
|
95
|
+
belongs_to reflections when the `include_reflections` is not false.
|
96
|
+
|
97
|
+
# Development
|
98
|
+
|
99
|
+
To run tests locally, spin up Fedora and Solr using `docker-compose up` then run tests using `bundle exec rspec`.
|
94
100
|
|
95
101
|
# Acknowledgments
|
96
102
|
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
volumes:
|
2
|
+
fedora:
|
3
|
+
solr:
|
4
|
+
|
5
|
+
services:
|
6
|
+
fedora:
|
7
|
+
image: ghcr.io/samvera/fcrepo4:4.7.5
|
8
|
+
volumes:
|
9
|
+
- fedora:/data
|
10
|
+
ports:
|
11
|
+
- '8986:8080'
|
12
|
+
|
13
|
+
solr:
|
14
|
+
image: solr:9
|
15
|
+
volumes:
|
16
|
+
- ./solr/conf:/opt/solr/core_conf
|
17
|
+
- solr:/var/solr
|
18
|
+
command:
|
19
|
+
- solr-precreate
|
20
|
+
- hydra-test
|
21
|
+
- /opt/solr/core_conf
|
22
|
+
environment:
|
23
|
+
- SOLR_MODULES=analysis-extras,extraction
|
24
|
+
ports:
|
25
|
+
- '8985:8983'
|
26
|
+
|
data/lib/speedy_af/base.rb
CHANGED
@@ -90,11 +90,11 @@ module SpeedyAF
|
|
90
90
|
reflections
|
91
91
|
end
|
92
92
|
|
93
|
-
def query_for_belongs_to(proxy_hash,
|
93
|
+
def query_for_belongs_to(proxy_hash, opts)
|
94
94
|
proxy_hash.collect do |_id, proxy|
|
95
|
-
proxy.belongs_to_reflections.collect do |_name, reflection|
|
96
|
-
|
97
|
-
|
95
|
+
proxy.belongs_to_reflections(only: opts[:load_reflections]).collect do |_name, reflection|
|
96
|
+
ids = proxy.attrs[predicate_for_reflection(reflection).to_sym]
|
97
|
+
ids.blank? ? nil : Array(ids).collect { |id| "id:#{id}" }.join(" OR ")
|
98
98
|
end.compact
|
99
99
|
end.flatten.join(" OR ")
|
100
100
|
end
|
@@ -103,7 +103,7 @@ module SpeedyAF
|
|
103
103
|
hash = {}
|
104
104
|
proxy_hash.each do |proxy_id, proxy|
|
105
105
|
proxy.belongs_to_reflections.each do |name, reflection|
|
106
|
-
doc = docs.find { |d|
|
106
|
+
doc = docs.find { |d| proxy.attrs[predicate_for_reflection(reflection).to_sym].include?(d.id) && d["has_model_ssim"].include?(reflection.class_name) }
|
107
107
|
next unless doc
|
108
108
|
hash[proxy_id] ||= {}
|
109
109
|
hash[proxy_id][name] = doc
|
@@ -113,9 +113,13 @@ module SpeedyAF
|
|
113
113
|
hash
|
114
114
|
end
|
115
115
|
|
116
|
-
def query_for_has_many(proxy_hash,
|
116
|
+
def query_for_has_many(proxy_hash, opts)
|
117
117
|
proxy_hash.collect do |id, proxy|
|
118
|
-
proxy.has_many_reflections.collect
|
118
|
+
proxy.has_many_reflections(only: opts[:load_reflections]).collect do |_name, reflection|
|
119
|
+
query = "#{predicate_for_reflection(reflection)}_ssim:#{id}"
|
120
|
+
query = "(#{query} AND has_model_ssim:#{reflection.class_name})"
|
121
|
+
query
|
122
|
+
end
|
119
123
|
end.flatten.join(" OR ")
|
120
124
|
end
|
121
125
|
|
@@ -125,7 +129,7 @@ module SpeedyAF
|
|
125
129
|
docs.each do |doc|
|
126
130
|
has_many_reflections.each do |name, reflection|
|
127
131
|
Array(doc["#{predicate_for_reflection(reflection)}_ssim"]).each do |proxy_id|
|
128
|
-
next unless proxy_hash.key?(proxy_id)
|
132
|
+
next unless proxy_hash.key?(proxy_id) && doc["has_model_ssim"].include?(reflection.class_name)
|
129
133
|
hash[proxy_id] ||= {}
|
130
134
|
hash[proxy_id][name] ||= []
|
131
135
|
hash[proxy_id][name] << doc
|
@@ -137,9 +141,9 @@ module SpeedyAF
|
|
137
141
|
hash
|
138
142
|
end
|
139
143
|
|
140
|
-
def query_for_subresources(proxy_hash,
|
144
|
+
def query_for_subresources(proxy_hash, opts)
|
141
145
|
proxy_hash.collect do |id, proxy|
|
142
|
-
proxy.subresource_reflections.collect { |name, _reflection| "id:#{id}/#{name}" }
|
146
|
+
proxy.subresource_reflections(only: opts[:load_reflections]).collect { |name, _reflection| "id:#{id}/#{name}" }
|
143
147
|
end.flatten.join(" OR ")
|
144
148
|
end
|
145
149
|
|
@@ -199,7 +203,6 @@ module SpeedyAF
|
|
199
203
|
|
200
204
|
def method_missing(sym, *args)
|
201
205
|
return real_object.send(sym, *args) if real?
|
202
|
-
|
203
206
|
if @attrs.key?(sym)
|
204
207
|
# Lazy convert the solr document into a speedy_af proxy object
|
205
208
|
@attrs[sym] = SpeedyAF::Base.for(@attrs[sym]) if @attrs[sym].is_a?(ActiveFedora::SolrHit)
|
@@ -223,18 +226,33 @@ module SpeedyAF
|
|
223
226
|
super
|
224
227
|
end
|
225
228
|
|
226
|
-
def subresource_reflections
|
229
|
+
def subresource_reflections(only: nil)
|
227
230
|
SpeedyAF::Base.model_reflections[:subresource][model] ||= model.reflections.select { |_name, reflection| reflection.is_a? ActiveFedora::Reflection::HasSubresourceReflection }
|
231
|
+
if only.is_a?(Array) && only.present?
|
232
|
+
SpeedyAF::Base.model_reflections[:subresource][model].select { |name, _reflection| only.include? name }
|
233
|
+
else
|
234
|
+
SpeedyAF::Base.model_reflections[:subresource][model]
|
235
|
+
end
|
228
236
|
end
|
229
237
|
|
230
238
|
# rubocop:disable Naming/PredicateName
|
231
|
-
def has_many_reflections
|
239
|
+
def has_many_reflections(only: nil)
|
232
240
|
SpeedyAF::Base.model_reflections[:has_many][model] ||= model.reflections.select { |_name, reflection| reflection.has_many? && reflection.respond_to?(:predicate_for_solr) }
|
241
|
+
if only.is_a?(Array) && only.present?
|
242
|
+
SpeedyAF::Base.model_reflections[:has_many][model].select { |name, _reflection| only.include? name }
|
243
|
+
else
|
244
|
+
SpeedyAF::Base.model_reflections[:has_many][model]
|
245
|
+
end
|
233
246
|
end
|
234
247
|
# rubocop:enable Naming/PredicateName
|
235
248
|
|
236
|
-
def belongs_to_reflections
|
249
|
+
def belongs_to_reflections(only: nil)
|
237
250
|
SpeedyAF::Base.model_reflections[:belongs_to][model] ||= model.reflections.select { |_name, reflection| reflection.belongs_to? && reflection.respond_to?(:predicate_for_solr) }
|
251
|
+
if only.is_a?(Array) && only.present?
|
252
|
+
SpeedyAF::Base.model_reflections[:belongs_to][model].select { |name, _reflection| only.include? name }
|
253
|
+
else
|
254
|
+
SpeedyAF::Base.model_reflections[:belongs_to][model]
|
255
|
+
end
|
238
256
|
end
|
239
257
|
|
240
258
|
protected
|
@@ -260,7 +278,7 @@ module SpeedyAF
|
|
260
278
|
attr_name, type, _stored, _indexed, _multi = k.scan(/^(.+)_(.+)(s)(i?)(m?)$/).first
|
261
279
|
return [k, v] if attr_name.nil?
|
262
280
|
value = Array(v).map { |m| transforms.fetch(type, transforms[nil]).call(m) }
|
263
|
-
value = value.first unless @model.respond_to?(:properties) && multiple?(@model.properties[attr_name])
|
281
|
+
value = value.first unless reflection_solr_fields(@model).include?(attr_name) || (@model.respond_to?(:properties) && multiple?(@model.properties[attr_name]))
|
264
282
|
[attr_name, value]
|
265
283
|
end
|
266
284
|
|
@@ -268,10 +286,15 @@ module SpeedyAF
|
|
268
286
|
prop.present? && prop.respond_to?(:multiple?) && prop.multiple?
|
269
287
|
end
|
270
288
|
|
289
|
+
def reflection_solr_fields(model)
|
290
|
+
return [] unless model.respond_to?(:reflections)
|
291
|
+
model.reflections.values.select { |v| v.belongs_to? && v.respond_to?(:predicate_for_solr) }.collect(&:predicate_for_solr)
|
292
|
+
end
|
293
|
+
|
271
294
|
def load_from_reflection(reflection, ids_only = false)
|
272
295
|
return load_through_reflection(reflection, ids_only) if reflection.options.key?(:through)
|
273
|
-
return load_belongs_to_reflection(reflection
|
274
|
-
return load_has_many_reflection(reflection
|
296
|
+
return load_belongs_to_reflection(reflection, ids_only) if reflection.belongs_to? && reflection.respond_to?(:predicate_for_solr)
|
297
|
+
return load_has_many_reflection(reflection, ids_only) if reflection.has_many? && reflection.respond_to?(:predicate_for_solr)
|
275
298
|
return load_subresource_content(reflection) if reflection.is_a?(ActiveFedora::Reflection::HasSubresourceReflection)
|
276
299
|
# :nocov:
|
277
300
|
raise NotAvailable, "`#{reflection.name}' cannot be quick-loaded. Falling back to model."
|
@@ -302,14 +325,18 @@ module SpeedyAF
|
|
302
325
|
ids
|
303
326
|
end
|
304
327
|
|
305
|
-
def load_belongs_to_reflection(
|
306
|
-
id = @attrs[
|
307
|
-
return id if ids_only
|
308
|
-
|
328
|
+
def load_belongs_to_reflection(reflection, ids_only = false)
|
329
|
+
id = @attrs[reflection.predicate_for_solr.to_sym]
|
330
|
+
return id.first if ids_only && Array(id).size == 1
|
331
|
+
return if id.blank?
|
332
|
+
query = Array(id).collect { |i| "id:#{i}" }.join(" OR ")
|
333
|
+
query = "(#{query}) AND has_model_ssim:#{reflection.class_name}"
|
334
|
+
obj = Base.where(query, rows: 1).first
|
335
|
+
ids_only ? obj&.id : obj
|
309
336
|
end
|
310
337
|
|
311
|
-
def load_has_many_reflection(
|
312
|
-
query =
|
338
|
+
def load_has_many_reflection(reflection, ids_only = false)
|
339
|
+
query = "#{reflection.predicate_for_solr}_ssim:#{id} AND has_model_ssim:#{reflection.class_name}"
|
313
340
|
return Base.where(query) unless ids_only
|
314
341
|
docs = ActiveFedora::SolrService.query query, rows: SOLR_ALL
|
315
342
|
docs.collect { |doc| doc['id'] }
|
data/lib/speedy_af/version.rb
CHANGED
data/spec/fixture_classes.rb
CHANGED
@@ -3,6 +3,10 @@ class IndexedFile < ActiveFedora::File
|
|
3
3
|
include SpeedyAF::IndexedContent
|
4
4
|
end
|
5
5
|
|
6
|
+
class SampleResource < ActiveFedora::File
|
7
|
+
include SpeedyAF::IndexedContent
|
8
|
+
end
|
9
|
+
|
6
10
|
class Chapter < ActiveFedora::Base
|
7
11
|
property :title, predicate: ::RDF::Vocab::DC.title, multiple: false do |index|
|
8
12
|
index.as :stored_searchable
|
@@ -12,18 +16,23 @@ class Chapter < ActiveFedora::Base
|
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
|
-
module
|
19
|
+
module TitleBehavior
|
16
20
|
def lowercase_title
|
17
21
|
title.downcase
|
18
22
|
end
|
23
|
+
|
24
|
+
def uppercase_title
|
25
|
+
title.upcase
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
29
|
class Book < ActiveFedora::Base
|
22
|
-
include
|
30
|
+
include TitleBehavior
|
23
31
|
include SpeedyAF::OrderedAggregationIndex
|
24
32
|
|
25
33
|
belongs_to :library, predicate: ::RDF::Vocab::DC.isPartOf
|
26
34
|
has_subresource 'indexed_file', class_name: 'IndexedFile'
|
35
|
+
has_subresource 'descMetadata', class_name: 'SampleResource'
|
27
36
|
has_subresource 'unindexed_file', class_name: 'ActiveFedora::File'
|
28
37
|
property :title, predicate: ::RDF::Vocab::DC.title, multiple: false do |index|
|
29
38
|
index.as :stored_searchable
|
@@ -33,14 +42,28 @@ class Book < ActiveFedora::Base
|
|
33
42
|
end
|
34
43
|
ordered_aggregation :chapters, through: :list_source
|
35
44
|
indexed_ordered_aggregation :chapters
|
45
|
+
end
|
36
46
|
|
37
|
-
|
38
|
-
|
47
|
+
class Comic < ActiveFedora::Base
|
48
|
+
include TitleBehavior
|
49
|
+
|
50
|
+
belongs_to :library, predicate: ::RDF::Vocab::DC.isPartOf
|
51
|
+
belongs_to :comic_shop, predicate: ::RDF::Vocab::DC.isPartOf
|
52
|
+
property :title, predicate: ::RDF::Vocab::DC.title, multiple: false do |index|
|
53
|
+
index.as :stored_searchable
|
54
|
+
end
|
55
|
+
property :publisher, predicate: ::RDF::Vocab::DC.publisher, multiple: false do |index|
|
56
|
+
index.as :stored_searchable
|
39
57
|
end
|
40
58
|
end
|
41
59
|
|
42
60
|
class Library < ActiveFedora::Base
|
43
|
-
has_many :books, predicate: ::RDF::Vocab::DC.isPartOf
|
61
|
+
has_many :books, class_name: 'Book', predicate: ::RDF::Vocab::DC.isPartOf
|
62
|
+
has_many :comics, class_name: 'Comic', predicate: ::RDF::Vocab::DC.isPartOf
|
63
|
+
end
|
64
|
+
|
65
|
+
class ComicShop < ActiveFedora::Base
|
66
|
+
has_many :comics, predicate: ::RDF::Vocab::DC.isPartOf
|
44
67
|
end
|
45
68
|
|
46
69
|
module SpeedySpecs
|
@@ -3,11 +3,13 @@ require 'spec_helper'
|
|
3
3
|
require 'rdf/vocab/dc'
|
4
4
|
|
5
5
|
describe SpeedyAF::Base do
|
6
|
-
before { load_fixture_classes!
|
6
|
+
before { load_fixture_classes! }
|
7
7
|
after { unload_fixture_classes! }
|
8
8
|
|
9
9
|
let!(:library) { Library.create }
|
10
|
+
let!(:comic_shop) { ComicShop.create }
|
10
11
|
let!(:book) { Book.new title: 'Ordered Things', publisher: 'ActiveFedora Performance LLC', library: library }
|
12
|
+
let!(:comic) { Comic.new title: 'Vestibulum velit nulla', publisher: 'SpeedyAF LLC', library: library, comic_shop: comic_shop }
|
11
13
|
let!(:chapters) do
|
12
14
|
[
|
13
15
|
Chapter.create(title: 'Chapter 3', contributor: ['Hopper', 'Lovelace', 'Johnson']),
|
@@ -31,12 +33,22 @@ describe SpeedyAF::Base do
|
|
31
33
|
Nigh tofth eliv ingdead.
|
32
34
|
IPSUM
|
33
35
|
end
|
36
|
+
let!(:metadata) do
|
37
|
+
<<-IPSUM
|
38
|
+
In scelerisque volutpat rutrum. Phasellus dictum velit at orci luctus convallis. Nulla rutrum
|
39
|
+
eget libero at sodales. Suspendisse potenti. Donec ut lobortis mi, ut venenatis diam. Phasellus
|
40
|
+
mi felis, cursus at lacinia vitae, aliquam vitae eros. Suspendisse tincidunt a massa in
|
41
|
+
condimentum. Nulla finibus risus quam, vel elementum enim sodales at.
|
42
|
+
IPSUM
|
43
|
+
end
|
34
44
|
let(:book_presenter) { described_class.find(book.id) }
|
45
|
+
let(:comic_presenter) { described_class.find(comic.id) }
|
35
46
|
|
36
47
|
context 'lightweight presenter' do
|
37
48
|
before do
|
38
49
|
book.indexed_file.content = indexed_content
|
39
50
|
book.unindexed_file.content = unindexed_content
|
51
|
+
book.descMetadata.content = metadata
|
40
52
|
book.chapters = chapters
|
41
53
|
book.ordered_chapters = chapters.sort_by(&:title)
|
42
54
|
book.save!
|
@@ -66,6 +78,7 @@ describe SpeedyAF::Base do
|
|
66
78
|
|
67
79
|
context 'reflections' do
|
68
80
|
let!(:library_presenter) { described_class.find(library.id) }
|
81
|
+
let!(:comic_shop_presenter) { described_class.find(comic_shop.id) }
|
69
82
|
|
70
83
|
it 'loads via indexed proxies' do
|
71
84
|
expect(book_presenter.chapter_ids).to match_array(book.chapter_ids)
|
@@ -82,27 +95,38 @@ describe SpeedyAF::Base do
|
|
82
95
|
|
83
96
|
it 'loads indexed subresources' do
|
84
97
|
ipsum_presenter = book_presenter.indexed_file
|
98
|
+
lorem_presenter = book_presenter.descMetadata
|
85
99
|
expect(ipsum_presenter.model).to eq(IndexedFile)
|
100
|
+
expect(lorem_presenter.model).to eq(SampleResource)
|
86
101
|
expect(ipsum_presenter.content).to eq(indexed_content)
|
102
|
+
expect(lorem_presenter.content).to eq(metadata)
|
87
103
|
expect(book_presenter).not_to be_real
|
88
104
|
expect(ipsum_presenter).not_to be_real
|
105
|
+
expect(lorem_presenter).not_to be_real
|
89
106
|
end
|
90
107
|
|
91
108
|
it 'loads has_many reflections' do
|
92
109
|
library.books.create(title: 'Ordered Things II')
|
110
|
+
library.comics.create(title: 'Comet in Moominland')
|
93
111
|
library.save
|
94
|
-
|
95
|
-
expect(
|
96
|
-
expect(presenter.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
112
|
+
expect(library_presenter.books.length).to eq(2)
|
113
|
+
expect(library_presenter.books.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
97
114
|
expect(library_presenter.book_ids).to match_array(library.book_ids)
|
115
|
+
expect(library_presenter.comics.length).to eq(1)
|
116
|
+
expect(library_presenter.comics.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
117
|
+
expect(library_presenter.comic_ids).to match_array(library.comic_ids)
|
98
118
|
expect(library_presenter).not_to be_real
|
99
119
|
end
|
100
120
|
|
101
121
|
it 'loads belongs_to reflections' do
|
102
|
-
|
103
|
-
expect(
|
104
|
-
expect(
|
105
|
-
expect(
|
122
|
+
comic.save!
|
123
|
+
expect(comic_presenter.library_id).to eq(library.id)
|
124
|
+
expect(comic_presenter.library).to be_a(described_class)
|
125
|
+
expect(comic_presenter.library.model).to eq(library.class)
|
126
|
+
expect(comic_presenter.comic_shop_id).to eq(comic_shop.id)
|
127
|
+
expect(comic_presenter.comic_shop).to be_a(described_class)
|
128
|
+
expect(comic_presenter.comic_shop.model).to eq(comic_shop.class)
|
129
|
+
expect(comic_presenter).not_to be_real
|
106
130
|
end
|
107
131
|
|
108
132
|
context 'missing parent id' do
|
@@ -129,15 +153,22 @@ describe SpeedyAF::Base do
|
|
129
153
|
|
130
154
|
it 'has already loaded has_many reflections' do
|
131
155
|
library.books.create(title: 'Ordered Things II')
|
156
|
+
library.comics.create(title: 'Comet in Moominland')
|
132
157
|
library.save
|
133
158
|
book_ids = library.book_ids
|
159
|
+
comic_ids = library.comic_ids
|
134
160
|
library_presenter = described_class.find(library.id, load_reflections: true)
|
135
161
|
expect(library_presenter.attrs).to include :books
|
162
|
+
expect(library_presenter.attrs).to include :comics
|
136
163
|
allow(ActiveFedora::SolrService).to receive(:query).and_call_original
|
137
|
-
|
138
|
-
|
139
|
-
expect(
|
164
|
+
books_presenter = library_presenter.books
|
165
|
+
comics_presenter = library_presenter.comics
|
166
|
+
expect(books_presenter.length).to eq(2)
|
167
|
+
expect(books_presenter.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
168
|
+
expect(comics_presenter.length).to eq(1)
|
169
|
+
expect(comics_presenter.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
140
170
|
expect(library_presenter.book_ids).to match_array(book_ids)
|
171
|
+
expect(library_presenter.comic_ids).to match_array(comic_ids)
|
141
172
|
expect(library_presenter).not_to be_real
|
142
173
|
expect(ActiveFedora::SolrService).not_to have_received(:query)
|
143
174
|
end
|
@@ -151,13 +182,61 @@ describe SpeedyAF::Base do
|
|
151
182
|
expect(book_presenter).not_to be_real
|
152
183
|
expect(ActiveFedora::SolrService).not_to have_received(:query)
|
153
184
|
end
|
185
|
+
|
186
|
+
context 'filtering' do
|
187
|
+
let(:book_presenter) { described_class.find(book.id, load_reflections: [:indexed_file]) }
|
188
|
+
let(:comic_presenter) { described_class.find(comic.id, load_reflections: [:comic_shop]) }
|
189
|
+
before { comic.save! }
|
190
|
+
|
191
|
+
it 'has already loaded filtered subresources' do
|
192
|
+
expect(book_presenter.attrs).to include :indexed_file
|
193
|
+
expect(book_presenter.attrs).to_not include :descMetadata
|
194
|
+
allow(ActiveFedora::SolrService).to receive(:query).and_call_original
|
195
|
+
ipsum_presenter = book_presenter.indexed_file
|
196
|
+
expect(ipsum_presenter.model).to eq(IndexedFile)
|
197
|
+
expect(ipsum_presenter.content).to eq(indexed_content)
|
198
|
+
expect(ipsum_presenter).not_to be_real
|
199
|
+
expect(ActiveFedora::SolrService).not_to have_received(:query)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'has already loaded filtered has_many reflections' do
|
203
|
+
library.books.create(title: 'Ordered Things II')
|
204
|
+
library.save
|
205
|
+
book_ids = library.book_ids
|
206
|
+
library_presenter = described_class.find(library.id, load_reflections: [:books])
|
207
|
+
expect(library_presenter.attrs).to include :books
|
208
|
+
expect(library_presenter.attrs).to_not include :comics
|
209
|
+
allow(ActiveFedora::SolrService).to receive(:query).and_call_original
|
210
|
+
presenter = library_presenter.books
|
211
|
+
expect(presenter.length).to eq(2)
|
212
|
+
expect(presenter.all? { |bp| bp.is_a?(described_class) }).to be_truthy
|
213
|
+
expect(library_presenter.book_ids).to match_array(book_ids)
|
214
|
+
expect(library_presenter).not_to be_real
|
215
|
+
expect(ActiveFedora::SolrService).not_to have_received(:query)
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'has already loaded belongs_to reflections and does not filter' do
|
219
|
+
expect(comic_presenter.attrs).to include :comic_shop
|
220
|
+
expect(comic_presenter.attrs).to include :library
|
221
|
+
allow(ActiveFedora::SolrService).to receive(:query).and_call_original
|
222
|
+
expect(comic_presenter.comic_shop_id).to eq(comic_shop.id)
|
223
|
+
expect(comic_presenter.comic_shop).to be_a(described_class)
|
224
|
+
expect(comic_presenter.comic_shop.model).to eq(comic_shop.class)
|
225
|
+
expect(comic_presenter).not_to be_real
|
226
|
+
expect(comic_presenter.library_id).to eq(library.id)
|
227
|
+
expect(comic_presenter.library).to be_a(described_class)
|
228
|
+
expect(comic_presenter.library.model).to eq(library.class)
|
229
|
+
expect(comic_presenter).not_to be_real
|
230
|
+
expect(ActiveFedora::SolrService).not_to have_received(:query)
|
231
|
+
end
|
232
|
+
end
|
154
233
|
end
|
155
234
|
end
|
156
235
|
|
157
236
|
context 'configuration' do
|
158
237
|
before do
|
159
238
|
described_class.config Book do
|
160
|
-
include
|
239
|
+
include TitleBehavior
|
161
240
|
self.defaults = { foo: 'bar!' }
|
162
241
|
end
|
163
242
|
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: speedy-af
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael B. Klein
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-08-06 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: active-fedora
|
@@ -196,6 +195,7 @@ files:
|
|
196
195
|
- LICENSE
|
197
196
|
- README.md
|
198
197
|
- Rakefile
|
198
|
+
- docker-compose.yml
|
199
199
|
- lib/speedy-af.rb
|
200
200
|
- lib/speedy_af.rb
|
201
201
|
- lib/speedy_af/base.rb
|
@@ -211,7 +211,6 @@ homepage: http://github.com/samvera-labs/speedy_af
|
|
211
211
|
licenses:
|
212
212
|
- APACHE2
|
213
213
|
metadata: {}
|
214
|
-
post_install_message:
|
215
214
|
rdoc_options: []
|
216
215
|
require_paths:
|
217
216
|
- lib
|
@@ -226,8 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
226
225
|
- !ruby/object:Gem::Version
|
227
226
|
version: '0'
|
228
227
|
requirements: []
|
229
|
-
rubygems_version: 3.5
|
230
|
-
signing_key:
|
228
|
+
rubygems_version: 3.6.5
|
231
229
|
specification_version: 4
|
232
230
|
summary: Performance enhancements for ActiveFedora
|
233
231
|
test_files: []
|