speedy-af 0.4.0 → 0.5.1
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/solr/conf/_rest_managed.json +3 -0
- data/solr/conf/admin-extra.html +31 -0
- data/solr/conf/elevate.xml +36 -0
- data/solr/conf/mapping-ISOLatin1Accent.txt +246 -0
- data/solr/conf/protwords.txt +21 -0
- data/solr/conf/schema.xml +367 -0
- data/solr/conf/scripts.conf +24 -0
- data/solr/conf/solrconfig.xml +327 -0
- data/solr/conf/spellings.txt +2 -0
- data/solr/conf/stopwords.txt +58 -0
- data/solr/conf/stopwords_en.txt +58 -0
- data/solr/conf/synonyms.txt +31 -0
- data/solr/conf/xslt/example.xsl +132 -0
- data/solr/conf/xslt/example_atom.xsl +67 -0
- data/solr/conf/xslt/example_rss.xsl +66 -0
- data/solr/conf/xslt/luke.xsl +337 -0
- data/spec/fixture_classes.rb +28 -5
- data/spec/integration/base_spec.rb +91 -12
- metadata +20 -6
@@ -0,0 +1,66 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
|
3
|
+
<!--
|
4
|
+
* Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
* contributor license agreements. See the NOTICE file distributed with
|
6
|
+
* this work for additional information regarding copyright ownership.
|
7
|
+
* The ASF licenses this file to You under the Apache License, Version 2.0
|
8
|
+
* (the "License"); you may not use this file except in compliance with
|
9
|
+
* the License. You may obtain a copy of the License at
|
10
|
+
*
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
*
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
* See the License for the specific language governing permissions and
|
17
|
+
* limitations under the License.
|
18
|
+
-->
|
19
|
+
|
20
|
+
<!--
|
21
|
+
Simple transform of Solr query results to RSS
|
22
|
+
-->
|
23
|
+
|
24
|
+
<xsl:stylesheet version='1.0'
|
25
|
+
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
|
26
|
+
|
27
|
+
<xsl:output
|
28
|
+
method="xml"
|
29
|
+
encoding="utf-8"
|
30
|
+
media-type="text/xml; charset=UTF-8"
|
31
|
+
/>
|
32
|
+
<xsl:template match='/'>
|
33
|
+
<rss version="2.0">
|
34
|
+
<channel>
|
35
|
+
<title>Example Solr RSS 2.0 Feed</title>
|
36
|
+
<link>http://localhost:8983/solr</link>
|
37
|
+
<description>
|
38
|
+
This has been formatted by the sample "example_rss.xsl" transform -
|
39
|
+
use your own XSLT to get a nicer RSS feed.
|
40
|
+
</description>
|
41
|
+
<language>en-us</language>
|
42
|
+
<docs>http://localhost:8983/solr</docs>
|
43
|
+
<xsl:apply-templates select="response/result/doc"/>
|
44
|
+
</channel>
|
45
|
+
</rss>
|
46
|
+
</xsl:template>
|
47
|
+
|
48
|
+
<!-- search results xslt -->
|
49
|
+
<xsl:template match="doc">
|
50
|
+
<xsl:variable name="id" select="str[@name='id']"/>
|
51
|
+
<xsl:variable name="timestamp" select="date[@name='timestamp']"/>
|
52
|
+
<item>
|
53
|
+
<title><xsl:value-of select="str[@name='name']"/></title>
|
54
|
+
<link>
|
55
|
+
http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
|
56
|
+
</link>
|
57
|
+
<description>
|
58
|
+
<xsl:value-of select="arr[@name='features']"/>
|
59
|
+
</description>
|
60
|
+
<pubDate><xsl:value-of select="$timestamp"/></pubDate>
|
61
|
+
<guid>
|
62
|
+
http://localhost:8983/solr/select?q=id:<xsl:value-of select="$id"/>
|
63
|
+
</guid>
|
64
|
+
</item>
|
65
|
+
</xsl:template>
|
66
|
+
</xsl:stylesheet>
|
@@ -0,0 +1,337 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!--
|
3
|
+
Licensed to the Apache Software Foundation (ASF) under one or more
|
4
|
+
contributor license agreements. See the NOTICE file distributed with
|
5
|
+
this work for additional information regarding copyright ownership.
|
6
|
+
The ASF licenses this file to You under the Apache License, Version 2.0
|
7
|
+
(the "License"); you may not use this file except in compliance with
|
8
|
+
the License. You may obtain a copy of the License at
|
9
|
+
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
See the License for the specific language governing permissions and
|
16
|
+
limitations under the License.
|
17
|
+
-->
|
18
|
+
|
19
|
+
|
20
|
+
<!--
|
21
|
+
Display the luke request handler with graphs
|
22
|
+
-->
|
23
|
+
<xsl:stylesheet
|
24
|
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
25
|
+
xmlns="http://www.w3.org/1999/xhtml"
|
26
|
+
version="1.0"
|
27
|
+
>
|
28
|
+
<xsl:output
|
29
|
+
method="html"
|
30
|
+
encoding="UTF-8"
|
31
|
+
media-type="text/html; charset=UTF-8"
|
32
|
+
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
|
33
|
+
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
|
34
|
+
/>
|
35
|
+
|
36
|
+
<xsl:variable name="title">Solr Luke Request Handler Response</xsl:variable>
|
37
|
+
|
38
|
+
<xsl:template match="/">
|
39
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
40
|
+
<head>
|
41
|
+
<link rel="stylesheet" type="text/css" href="solr-admin.css"/>
|
42
|
+
<link rel="icon" href="favicon.ico" type="image/ico"/>
|
43
|
+
<link rel="shortcut icon" href="favicon.ico" type="image/ico"/>
|
44
|
+
<title>
|
45
|
+
<xsl:value-of select="$title"/>
|
46
|
+
</title>
|
47
|
+
<xsl:call-template name="css"/>
|
48
|
+
|
49
|
+
</head>
|
50
|
+
<body>
|
51
|
+
<h1>
|
52
|
+
<xsl:value-of select="$title"/>
|
53
|
+
</h1>
|
54
|
+
<div class="doc">
|
55
|
+
<ul>
|
56
|
+
<xsl:if test="response/lst[@name='index']">
|
57
|
+
<li>
|
58
|
+
<a href="#index">Index Statistics</a>
|
59
|
+
</li>
|
60
|
+
</xsl:if>
|
61
|
+
<xsl:if test="response/lst[@name='fields']">
|
62
|
+
<li>
|
63
|
+
<a href="#fields">Field Statistics</a>
|
64
|
+
<ul>
|
65
|
+
<xsl:for-each select="response/lst[@name='fields']/lst">
|
66
|
+
<li>
|
67
|
+
<a href="#{@name}">
|
68
|
+
<xsl:value-of select="@name"/>
|
69
|
+
</a>
|
70
|
+
</li>
|
71
|
+
</xsl:for-each>
|
72
|
+
</ul>
|
73
|
+
</li>
|
74
|
+
</xsl:if>
|
75
|
+
<xsl:if test="response/lst[@name='doc']">
|
76
|
+
<li>
|
77
|
+
<a href="#doc">Document statistics</a>
|
78
|
+
</li>
|
79
|
+
</xsl:if>
|
80
|
+
</ul>
|
81
|
+
</div>
|
82
|
+
<xsl:if test="response/lst[@name='index']">
|
83
|
+
<h2><a name="index"/>Index Statistics</h2>
|
84
|
+
<xsl:apply-templates select="response/lst[@name='index']"/>
|
85
|
+
</xsl:if>
|
86
|
+
<xsl:if test="response/lst[@name='fields']">
|
87
|
+
<h2><a name="fields"/>Field Statistics</h2>
|
88
|
+
<xsl:apply-templates select="response/lst[@name='fields']"/>
|
89
|
+
</xsl:if>
|
90
|
+
<xsl:if test="response/lst[@name='doc']">
|
91
|
+
<h2><a name="doc"/>Document statistics</h2>
|
92
|
+
<xsl:apply-templates select="response/lst[@name='doc']"/>
|
93
|
+
</xsl:if>
|
94
|
+
</body>
|
95
|
+
</html>
|
96
|
+
</xsl:template>
|
97
|
+
|
98
|
+
<xsl:template match="lst">
|
99
|
+
<xsl:if test="parent::lst">
|
100
|
+
<tr>
|
101
|
+
<td colspan="2">
|
102
|
+
<div class="doc">
|
103
|
+
<xsl:call-template name="list"/>
|
104
|
+
</div>
|
105
|
+
</td>
|
106
|
+
</tr>
|
107
|
+
</xsl:if>
|
108
|
+
<xsl:if test="not(parent::lst)">
|
109
|
+
<div class="doc">
|
110
|
+
<xsl:call-template name="list"/>
|
111
|
+
</div>
|
112
|
+
</xsl:if>
|
113
|
+
</xsl:template>
|
114
|
+
|
115
|
+
<xsl:template name="list">
|
116
|
+
<xsl:if test="count(child::*)>0">
|
117
|
+
<table>
|
118
|
+
<thead>
|
119
|
+
<tr>
|
120
|
+
<th colspan="2">
|
121
|
+
<p>
|
122
|
+
<a name="{@name}"/>
|
123
|
+
</p>
|
124
|
+
<xsl:value-of select="@name"/>
|
125
|
+
</th>
|
126
|
+
</tr>
|
127
|
+
</thead>
|
128
|
+
<tbody>
|
129
|
+
<xsl:choose>
|
130
|
+
<xsl:when
|
131
|
+
test="@name='histogram'">
|
132
|
+
<tr>
|
133
|
+
<td colspan="2">
|
134
|
+
<xsl:call-template name="histogram"/>
|
135
|
+
</td>
|
136
|
+
</tr>
|
137
|
+
</xsl:when>
|
138
|
+
<xsl:otherwise>
|
139
|
+
<xsl:apply-templates/>
|
140
|
+
</xsl:otherwise>
|
141
|
+
</xsl:choose>
|
142
|
+
</tbody>
|
143
|
+
</table>
|
144
|
+
</xsl:if>
|
145
|
+
</xsl:template>
|
146
|
+
|
147
|
+
<xsl:template name="histogram">
|
148
|
+
<div class="doc">
|
149
|
+
<xsl:call-template name="barchart">
|
150
|
+
<xsl:with-param name="max_bar_width">50</xsl:with-param>
|
151
|
+
<xsl:with-param name="iwidth">800</xsl:with-param>
|
152
|
+
<xsl:with-param name="iheight">160</xsl:with-param>
|
153
|
+
<xsl:with-param name="fill">blue</xsl:with-param>
|
154
|
+
</xsl:call-template>
|
155
|
+
</div>
|
156
|
+
</xsl:template>
|
157
|
+
|
158
|
+
<xsl:template name="barchart">
|
159
|
+
<xsl:param name="max_bar_width"/>
|
160
|
+
<xsl:param name="iwidth"/>
|
161
|
+
<xsl:param name="iheight"/>
|
162
|
+
<xsl:param name="fill"/>
|
163
|
+
<xsl:variable name="max">
|
164
|
+
<xsl:for-each select="int">
|
165
|
+
<xsl:sort data-type="number" order="descending"/>
|
166
|
+
<xsl:if test="position()=1">
|
167
|
+
<xsl:value-of select="."/>
|
168
|
+
</xsl:if>
|
169
|
+
</xsl:for-each>
|
170
|
+
</xsl:variable>
|
171
|
+
<xsl:variable name="bars">
|
172
|
+
<xsl:value-of select="count(int)"/>
|
173
|
+
</xsl:variable>
|
174
|
+
<xsl:variable name="bar_width">
|
175
|
+
<xsl:choose>
|
176
|
+
<xsl:when test="$max_bar_width < ($iwidth div $bars)">
|
177
|
+
<xsl:value-of select="$max_bar_width"/>
|
178
|
+
</xsl:when>
|
179
|
+
<xsl:otherwise>
|
180
|
+
<xsl:value-of select="$iwidth div $bars"/>
|
181
|
+
</xsl:otherwise>
|
182
|
+
</xsl:choose>
|
183
|
+
</xsl:variable>
|
184
|
+
<table class="histogram">
|
185
|
+
<tbody>
|
186
|
+
<tr>
|
187
|
+
<xsl:for-each select="int">
|
188
|
+
<td>
|
189
|
+
<xsl:value-of select="."/>
|
190
|
+
<div class="histogram">
|
191
|
+
<xsl:attribute name="style">background-color: <xsl:value-of select="$fill"/>; width: <xsl:value-of select="$bar_width"/>px; height: <xsl:value-of select="($iheight*number(.)) div $max"/>px;</xsl:attribute>
|
192
|
+
</div>
|
193
|
+
</td>
|
194
|
+
</xsl:for-each>
|
195
|
+
</tr>
|
196
|
+
<tr>
|
197
|
+
<xsl:for-each select="int">
|
198
|
+
<td>
|
199
|
+
<xsl:value-of select="@name"/>
|
200
|
+
</td>
|
201
|
+
</xsl:for-each>
|
202
|
+
</tr>
|
203
|
+
</tbody>
|
204
|
+
</table>
|
205
|
+
</xsl:template>
|
206
|
+
|
207
|
+
<xsl:template name="keyvalue">
|
208
|
+
<xsl:choose>
|
209
|
+
<xsl:when test="@name">
|
210
|
+
<tr>
|
211
|
+
<td class="name">
|
212
|
+
<xsl:value-of select="@name"/>
|
213
|
+
</td>
|
214
|
+
<td class="value">
|
215
|
+
<xsl:value-of select="."/>
|
216
|
+
</td>
|
217
|
+
</tr>
|
218
|
+
</xsl:when>
|
219
|
+
<xsl:otherwise>
|
220
|
+
<xsl:value-of select="."/>
|
221
|
+
</xsl:otherwise>
|
222
|
+
</xsl:choose>
|
223
|
+
</xsl:template>
|
224
|
+
|
225
|
+
<xsl:template match="int|bool|long|float|double|uuid|date">
|
226
|
+
<xsl:call-template name="keyvalue"/>
|
227
|
+
</xsl:template>
|
228
|
+
|
229
|
+
<xsl:template match="arr">
|
230
|
+
<tr>
|
231
|
+
<td class="name">
|
232
|
+
<xsl:value-of select="@name"/>
|
233
|
+
</td>
|
234
|
+
<td class="value">
|
235
|
+
<ul>
|
236
|
+
<xsl:for-each select="child::*">
|
237
|
+
<li>
|
238
|
+
<xsl:apply-templates/>
|
239
|
+
</li>
|
240
|
+
</xsl:for-each>
|
241
|
+
</ul>
|
242
|
+
</td>
|
243
|
+
</tr>
|
244
|
+
</xsl:template>
|
245
|
+
|
246
|
+
<xsl:template match="str">
|
247
|
+
<xsl:choose>
|
248
|
+
<xsl:when test="@name='schema' or @name='index' or @name='flags'">
|
249
|
+
<xsl:call-template name="schema"/>
|
250
|
+
</xsl:when>
|
251
|
+
<xsl:otherwise>
|
252
|
+
<xsl:call-template name="keyvalue"/>
|
253
|
+
</xsl:otherwise>
|
254
|
+
</xsl:choose>
|
255
|
+
</xsl:template>
|
256
|
+
|
257
|
+
<xsl:template name="schema">
|
258
|
+
<tr>
|
259
|
+
<td class="name">
|
260
|
+
<xsl:value-of select="@name"/>
|
261
|
+
</td>
|
262
|
+
<td class="value">
|
263
|
+
<xsl:if test="contains(.,'unstored')">
|
264
|
+
<xsl:value-of select="."/>
|
265
|
+
</xsl:if>
|
266
|
+
<xsl:if test="not(contains(.,'unstored'))">
|
267
|
+
<xsl:call-template name="infochar2string">
|
268
|
+
<xsl:with-param name="charList">
|
269
|
+
<xsl:value-of select="."/>
|
270
|
+
</xsl:with-param>
|
271
|
+
</xsl:call-template>
|
272
|
+
</xsl:if>
|
273
|
+
</td>
|
274
|
+
</tr>
|
275
|
+
</xsl:template>
|
276
|
+
|
277
|
+
<xsl:template name="infochar2string">
|
278
|
+
<xsl:param name="i">1</xsl:param>
|
279
|
+
<xsl:param name="charList"/>
|
280
|
+
|
281
|
+
<xsl:variable name="char">
|
282
|
+
<xsl:value-of select="substring($charList,$i,1)"/>
|
283
|
+
</xsl:variable>
|
284
|
+
<xsl:choose>
|
285
|
+
<xsl:when test="$char='I'">
|
286
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='I']"/> - </xsl:when>
|
287
|
+
<xsl:when test="$char='T'">
|
288
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='T']"/> - </xsl:when>
|
289
|
+
<xsl:when test="$char='S'">
|
290
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='S']"/> - </xsl:when>
|
291
|
+
<xsl:when test="$char='M'">
|
292
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='M']"/> - </xsl:when>
|
293
|
+
<xsl:when test="$char='V'">
|
294
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='V']"/> - </xsl:when>
|
295
|
+
<xsl:when test="$char='o'">
|
296
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='o']"/> - </xsl:when>
|
297
|
+
<xsl:when test="$char='p'">
|
298
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='p']"/> - </xsl:when>
|
299
|
+
<xsl:when test="$char='O'">
|
300
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='O']"/> - </xsl:when>
|
301
|
+
<xsl:when test="$char='L'">
|
302
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='L']"/> - </xsl:when>
|
303
|
+
<xsl:when test="$char='B'">
|
304
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='B']"/> - </xsl:when>
|
305
|
+
<xsl:when test="$char='C'">
|
306
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='C']"/> - </xsl:when>
|
307
|
+
<xsl:when test="$char='f'">
|
308
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='f']"/> - </xsl:when>
|
309
|
+
<xsl:when test="$char='l'">
|
310
|
+
<xsl:value-of select="/response/lst[@name='info']/lst/str[@name='l']"/> -
|
311
|
+
</xsl:when>
|
312
|
+
</xsl:choose>
|
313
|
+
|
314
|
+
<xsl:if test="not($i>=string-length($charList))">
|
315
|
+
<xsl:call-template name="infochar2string">
|
316
|
+
<xsl:with-param name="i">
|
317
|
+
<xsl:value-of select="$i+1"/>
|
318
|
+
</xsl:with-param>
|
319
|
+
<xsl:with-param name="charList">
|
320
|
+
<xsl:value-of select="$charList"/>
|
321
|
+
</xsl:with-param>
|
322
|
+
</xsl:call-template>
|
323
|
+
</xsl:if>
|
324
|
+
</xsl:template>
|
325
|
+
<xsl:template name="css">
|
326
|
+
<style type="text/css">
|
327
|
+
<![CDATA[
|
328
|
+
td.name {font-style: italic; font-size:80%; }
|
329
|
+
.doc { margin: 0.5em; border: solid grey 1px; }
|
330
|
+
.exp { display: none; font-family: monospace; white-space: pre; }
|
331
|
+
div.histogram { background: none repeat scroll 0%; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;}
|
332
|
+
table.histogram { width: auto; vertical-align: bottom; }
|
333
|
+
table.histogram td, table.histogram th { text-align: center; vertical-align: bottom; border-bottom: 1px solid #ff9933; width: auto; }
|
334
|
+
]]>
|
335
|
+
</style>
|
336
|
+
</xsl:template>
|
337
|
+
</xsl:stylesheet>
|
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
|
|