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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fd6d0ac71c3da9c7807fe63bf98774a75abf4796130be797e19a9eba4ac6292
4
- data.tar.gz: 549a1835b24011c7ebebef142654afb7c8ab0afdd0b70e39a713e7e1c9055dca
3
+ metadata.gz: 0ff0f3d554f80151433f700cfae02d61d3c271fbcfb1cefe132d8a9e0e518734
4
+ data.tar.gz: 01433ba5beca3308fa708191c76a2be9df2b5682be1ae41a3dc08f6ad6dd42af
5
5
  SHA512:
6
- metadata.gz: 50e4f754a2f59937b4d08a3ccd9d460e64ecbba50d1e5eed821a28fcb77aab99f77a62307c9185269d27ac1f0baab58e72f8e56cc9debbab71bd99c2c54700e5
7
- data.tar.gz: f0f1e0fd4e04f475085ada08769cf9617a95f6ddcd2b0955cea44adc91284844862d0c3c6729c9bc17c32ba456067e448d83c81be9899520003b5dea3b142ed1
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
 
@@ -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
+
@@ -90,11 +90,11 @@ module SpeedyAF
90
90
  reflections
91
91
  end
92
92
 
93
- def query_for_belongs_to(proxy_hash, _opts)
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
- id = proxy.attrs[predicate_for_reflection(reflection).to_sym]
97
- id.blank? ? nil : "id:#{id}"
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| d.id == proxy.attrs[predicate_for_reflection(reflection).to_sym] }
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, _opts)
116
+ def query_for_has_many(proxy_hash, opts)
117
117
  proxy_hash.collect do |id, proxy|
118
- proxy.has_many_reflections.collect { |_name, reflection| "#{predicate_for_reflection(reflection)}_ssim:#{id}" }
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, _opts)
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.predicate_for_solr, ids_only) if reflection.belongs_to? && reflection.respond_to?(:predicate_for_solr)
274
- return load_has_many_reflection(reflection.predicate_for_solr, ids_only) if reflection.has_many? && reflection.respond_to?(:predicate_for_solr)
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(predicate, ids_only = false)
306
- id = @attrs[predicate.to_sym]
307
- return id if ids_only
308
- Base.find(id)
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(predicate, ids_only = false)
312
- query = %(#{predicate}_ssim:#{id})
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'] }
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module SpeedyAF
3
- VERSION = '0.4.0'
3
+ VERSION = '0.5.0'
4
4
  end
@@ -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 DowncaseBehavior
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 DowncaseBehavior
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
- def uppercase_title
38
- title.upcase
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
- presenter = library_presenter.books
95
- expect(presenter.length).to eq(2)
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
- expect(book_presenter.library_id).to eq(library.id)
103
- expect(book_presenter.library).to be_a(described_class)
104
- expect(book_presenter.library.model).to eq(library.class)
105
- expect(book_presenter).not_to be_real
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
- presenter = library_presenter.books
138
- expect(presenter.length).to eq(2)
139
- expect(presenter.all? { |bp| bp.is_a?(described_class) }).to be_truthy
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 DowncaseBehavior
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.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: 2024-11-19 00:00:00.000000000 Z
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.16
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: []