krikri 0.7.2 → 0.7.3
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/app/controllers/krikri/records_controller.rb +2 -2
- data/app/helpers/krikri/application_helper.rb +1 -1
- data/app/models/krikri/provider.rb +137 -44
- data/app/models/krikri/qa_report.rb +1 -1
- data/app/models/krikri/validation_report.rb +3 -1
- data/app/views/krikri/providers/index.html.erb +1 -1
- data/lib/krikri/harvesters/oai_harvester.rb +6 -16
- data/lib/krikri/parser.rb +58 -7
- data/lib/krikri/version.rb +1 -1
- data/lib/tasks/krikri.rake +12 -7
- data/spec/controllers/providers_controller_spec.rb +2 -1
- data/spec/factories/krikri_provider.rb +2 -4
- data/spec/helpers/krikri/application_helper_spec.rb +2 -2
- data/spec/internal/db/test.sqlite3 +0 -0
- data/spec/internal/log/test.log +27735 -0
- data/spec/lib/krikri/harvesters/oai_harvester_spec.rb +14 -19
- data/spec/lib/krikri/parser_value_array_spec.rb +47 -4
- data/spec/lib/krikri/search_index_spec.rb +1 -0
- data/spec/models/provider_spec.rb +104 -65
- data/spec/models/qa_report_spec.rb +5 -3
- data/spec/models/validation_report_spec.rb +2 -2
- data/spec/support/shared_contexts/indexed_item.rb +17 -11
- data/spec/support/shared_examples/active_model_lint.rb +14 -0
- data/spec/views/krikri/providers/index.html.erb_spec.rb +2 -2
- data/spec/views/krikri/providers/show.html.erb_spec.rb +1 -1
- data/spec/views/krikri/reports/index.html.erb_spec.rb +1 -1
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96bca4e27356f470641703f33e18cf175ebd69ff
|
4
|
+
data.tar.gz: bc9ae30eda3a0afb8bddf6acf303b4613f74a779
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4d51fb35e997ca7ec9100d2d8ea55fbb54dcda052374794e3c40518f77da172dfa690e2d65f2be238beefca0447d1a08272483b4618d28ded01ee78f9037136
|
7
|
+
data.tar.gz: 6df381f8ac7c5defc2ac5a05421b24a80cec0f948c3481b06f4e5b8989a5750b65ed33acd988f933dce334dcb5328017961f4c61cb4e39b5b9d7969a9c14037c
|
@@ -134,9 +134,9 @@ module Krikri
|
|
134
134
|
# @param [Hash] user_parameters a hash of user-supplied parameters.
|
135
135
|
def records_by_provider(solr_params, user_params)
|
136
136
|
if @provider_id.present?
|
137
|
-
|
137
|
+
rdf_subject = Krikri::Provider.base_uri + @provider_id
|
138
138
|
solr_params[:fq] ||= []
|
139
|
-
solr_params[:fq] << "provider_id:\"#{
|
139
|
+
solr_params[:fq] << "provider_id:\"#{rdf_subject}\""
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
@@ -15,7 +15,7 @@ module Krikri
|
|
15
15
|
# @return [String]
|
16
16
|
def provider_name(provider)
|
17
17
|
provider = Krikri::Provider.find(provider) if provider.is_a? String
|
18
|
-
provider.present? ? provider.
|
18
|
+
provider.present? ? provider.name : 'All Providers'
|
19
19
|
end
|
20
20
|
|
21
21
|
##
|
@@ -1,80 +1,173 @@
|
|
1
1
|
module Krikri
|
2
2
|
##
|
3
|
-
#
|
3
|
+
# Provider is an ActiveModel object. It represents a provider that has been
|
4
|
+
# indexed in Solr.
|
4
5
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
|
9
|
-
|
6
|
+
# This is a read-only object. It does not write new providers to Solr, nor
|
7
|
+
# does it update or delete providers.
|
8
|
+
#
|
9
|
+
# A DPLA::MAP::Agent object can be constructed from an instance of this
|
10
|
+
# ActiveModel object using the :agent method. The DPLA::MAP::Agent object
|
11
|
+
# interacts with Marmotta, rather than Solr.
|
12
|
+
#
|
13
|
+
# @example Krikri::Provider.find(rdf_subject: 'http://blah.com/123').agent
|
14
|
+
# => [DPLA::MAP::Agent]
|
15
|
+
#
|
16
|
+
class Provider
|
17
|
+
include ActiveModel::Validations
|
18
|
+
include ActiveModel::Conversion
|
19
|
+
extend ActiveModel::Naming
|
20
|
+
|
21
|
+
##
|
22
|
+
# @!attribute :rdf_subject [String] the URI identifying the provider
|
23
|
+
# @example: "http://blah.com/contributor/123"
|
24
|
+
#
|
25
|
+
# @!attribute :id [String] the stub id
|
26
|
+
# @example: "123"
|
27
|
+
#
|
28
|
+
# @!attribute :name [String] the human-redable name of the provider
|
29
|
+
#
|
30
|
+
# @!attribute :agent [DPLA::MAP::Agent] an ActiveTriples representation of
|
31
|
+
# the provider, read from Marmotta.
|
32
|
+
attr_accessor :rdf_subject, :name
|
33
|
+
attr_reader :agent, :id
|
34
|
+
|
35
|
+
##
|
36
|
+
# Initializes a Provider object.
|
37
|
+
#
|
38
|
+
# @param attributes [Hash]
|
39
|
+
# If the params Hash contains a valid value for :rdf_subject, the model can
|
40
|
+
# extrapolate all other attributes.
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# Krikri::Provider.new({ rdf_subject: 'http:://blah.com/contributor/123',
|
44
|
+
# name: 'Moomin Valley Historical Society' })
|
45
|
+
#
|
46
|
+
# @raise [NoMethodError] if the params Hash includes a key that does not
|
47
|
+
# match listed attr_accessors
|
48
|
+
#
|
49
|
+
# @return [<Krikri::Provider>]
|
50
|
+
def initialize(attributes = {})
|
51
|
+
attributes.each do |name, value|
|
52
|
+
send("#{name}=", value)
|
53
|
+
end
|
54
|
+
end
|
10
55
|
|
11
56
|
##
|
12
57
|
# Gives a list of all providers, ignoring those with no URI (bnodes).
|
13
58
|
#
|
59
|
+
# Providers will be initialized with both an :rdf_subject and a :name,
|
60
|
+
# if both exist in the Solr index.
|
61
|
+
#
|
14
62
|
# @return [Array<Krikri::Provider>]
|
15
63
|
def self.all
|
16
64
|
query_params = { :rows => 0,
|
17
65
|
:id => '*:*',
|
18
|
-
|
66
|
+
:facet => true,
|
67
|
+
'facet.pivot' => 'provider_id,provider_name' }
|
19
68
|
response = Krikri::SolrResponseBuilder.new(query_params).response
|
20
|
-
|
21
|
-
|
22
|
-
|
69
|
+
|
70
|
+
response.facet_pivot['provider_id,provider_name'].map do |facet|
|
71
|
+
rdf_subject = facet['value']
|
72
|
+
name = facet['pivot'].present? ? facet['pivot'].first['value'] : nil
|
73
|
+
provider = new({ :rdf_subject => rdf_subject, :name => name })
|
74
|
+
provider.valid_rdf_subject? ? provider : nil
|
23
75
|
end.compact
|
24
76
|
end
|
25
77
|
|
26
78
|
##
|
27
|
-
#
|
28
|
-
#
|
79
|
+
# Finds a provider in Solr that matches the given ID, ignoring bnodes.
|
80
|
+
#
|
81
|
+
# @param [String] :id or :rdf_subject
|
29
82
|
#
|
30
83
|
# @return [Krikri::Provider]
|
31
|
-
# @todo Use {ActiveTriples}/{RDF::Repository} to populate the object
|
32
84
|
def self.find(id)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
85
|
+
rdf_subject = id.start_with?(base_uri) ? id : base_uri + id
|
86
|
+
query_params = { :rows => 1,
|
87
|
+
:q => rdf_subject,
|
88
|
+
:qf => 'provider_id',
|
89
|
+
:fl => 'provider_id provider_name' }
|
90
|
+
response = Krikri::SolrResponseBuilder.new(query_params).response
|
91
|
+
return nil unless response.docs.count > 0
|
92
|
+
new({ :rdf_subject => rdf_subject,
|
93
|
+
:name => response.docs.first['provider_name'].first })
|
38
94
|
end
|
39
95
|
|
40
96
|
##
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
97
|
+
# Get the base of the :rdf_subject for any provider
|
98
|
+
# @return [String] ending in "/"
|
99
|
+
def self.base_uri
|
100
|
+
base_uri = Krikri::Settings.prov.provider_base
|
101
|
+
base_uri.end_with?('/') ? base_uri : base_uri << '/'
|
102
|
+
end
|
103
|
+
|
104
|
+
def id
|
105
|
+
@id ||= local_name
|
106
|
+
end
|
49
107
|
|
50
|
-
|
108
|
+
def name
|
109
|
+
@name ||= initialize_name
|
110
|
+
end
|
111
|
+
|
112
|
+
def agent
|
113
|
+
@agent ||= initialize_agent
|
51
114
|
end
|
52
115
|
|
53
116
|
##
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
[:record, RDF.type, RDF::ORE.Aggregation])
|
117
|
+
# Tests for providers that have valid a :rdf_subject (not a bnode).
|
118
|
+
# A valid :rdf_subject does not necessarily match and :rdf_subject in the
|
119
|
+
# Solr index, but it has the correct URI format.
|
120
|
+
def valid_rdf_subject?
|
121
|
+
return false unless rdf_subject.present?
|
122
|
+
rdf_subject.start_with?(self.class.base_uri) ? true : false
|
123
|
+
end
|
62
124
|
|
63
|
-
|
64
|
-
|
65
|
-
|
125
|
+
##
|
126
|
+
# Required ActiveModel method.
|
127
|
+
def persisted?
|
128
|
+
false
|
66
129
|
end
|
67
130
|
|
131
|
+
private
|
132
|
+
|
68
133
|
##
|
69
|
-
#
|
70
|
-
|
71
|
-
|
134
|
+
# Gives the last path fragment for :rdf_subject in HTML escaped form,
|
135
|
+
# ignoring :rdf_subjects, ignoring bnodes.
|
136
|
+
#
|
137
|
+
# @example
|
138
|
+
# Given: rdf_subject == 'http://my_domain/blah/0123'
|
139
|
+
# local_name == '0123'
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
def local_name
|
143
|
+
return nil unless valid_rdf_subject?
|
144
|
+
rdf_subject.split('/').last.html_safe
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Gives the :provider_name associated with a provider's :rdf_subject
|
149
|
+
# (ie. :provider_id) in Solr, ignoring bnodes.
|
150
|
+
#
|
151
|
+
# @return [String]
|
152
|
+
def initialize_name
|
153
|
+
return nil unless valid_rdf_subject?
|
154
|
+
query_params = { :rows => 1,
|
155
|
+
:q => rdf_subject,
|
156
|
+
:qf => 'provider_id',
|
157
|
+
:fl => 'provider_name' }
|
158
|
+
response = Krikri::SolrResponseBuilder.new(query_params).response
|
159
|
+
return nil unless response.docs.count > 0
|
160
|
+
response.docs.first['provider_name'].first
|
72
161
|
end
|
73
162
|
|
74
163
|
##
|
75
|
-
#
|
76
|
-
|
77
|
-
|
164
|
+
# Creates DPLA::MAP::Agent object from the :rdf_subject and :name, ignoring
|
165
|
+
# bnodes.
|
166
|
+
#
|
167
|
+
# @return [DPLA::MAP::Agent]
|
168
|
+
def initialize_agent
|
169
|
+
return nil unless valid_rdf_subject?
|
170
|
+
DPLA::MAP::Agent.new(rdf_subject).tap { |agent| agent.label = name }
|
78
171
|
end
|
79
172
|
end
|
80
173
|
end
|
@@ -136,7 +136,7 @@ module Krikri
|
|
136
136
|
# @todo figure out a better relations pattern between {ActiveRecord} objects
|
137
137
|
# and {ActiveTriples}
|
138
138
|
def build_provider
|
139
|
-
Krikri::Provider.
|
139
|
+
Krikri::Provider.new(:rdf_subject => provider).agent
|
140
140
|
end
|
141
141
|
|
142
142
|
private
|
@@ -63,9 +63,11 @@ module Krikri
|
|
63
63
|
|
64
64
|
private
|
65
65
|
|
66
|
+
##
|
67
|
+
# Get the full URI identifier for the provider
|
66
68
|
def provider_uri
|
67
69
|
return unless provider_id.present?
|
68
|
-
Krikri::Provider.
|
70
|
+
Krikri::Provider.base_uri + provider_id
|
69
71
|
end
|
70
72
|
end
|
71
73
|
end
|
@@ -184,26 +184,16 @@ module Krikri::Harvesters
|
|
184
184
|
|
185
185
|
##
|
186
186
|
# Transforms an OAI::Record to xml suitable for saving with the
|
187
|
-
# OriginalRecord
|
187
|
+
# OriginalRecord. It's necessary to build a new document and add the
|
188
|
+
# namespace manually to normalize record output between `ListRecords` and
|
189
|
+
# `GetRecord` requests.
|
188
190
|
#
|
189
191
|
# @param rec [OAI::Record]
|
190
192
|
# @return [String] an xml string
|
191
193
|
def record_xml(rec)
|
192
|
-
doc = Nokogiri
|
193
|
-
|
194
|
-
|
195
|
-
xml.identifier rec.header.identifier
|
196
|
-
xml.datestamp rec.header.datestamp
|
197
|
-
rec.header.set_spec.each do |set|
|
198
|
-
xml.set_spec set.text
|
199
|
-
end
|
200
|
-
}
|
201
|
-
xml << rec.metadata.to_s unless rec.metadata.nil?
|
202
|
-
xml << rec.about.to_s unless rec.about.nil?
|
203
|
-
}
|
204
|
-
end
|
205
|
-
doc.doc.at_css('header')['status'] = rec.header.status if
|
206
|
-
rec.header.status
|
194
|
+
doc = Nokogiri.XML(rec._source.to_s)
|
195
|
+
doc.root
|
196
|
+
.add_namespace_definition(nil, 'http://www.openarchives.org/OAI/2.0/')
|
207
197
|
doc.to_xml
|
208
198
|
end
|
209
199
|
end
|
data/lib/krikri/parser.rb
CHANGED
@@ -273,17 +273,54 @@ module Krikri
|
|
273
273
|
end
|
274
274
|
|
275
275
|
##
|
276
|
+
# @example selecting by presence of an attribute; returns all nodes where
|
277
|
+
# `#attribute?(:type)` is true
|
278
|
+
#
|
279
|
+
# match_attribute(:type)
|
280
|
+
#
|
281
|
+
# @example selecting by the value of an attribute; returns all nodes with
|
282
|
+
# `#attribute(:type) == other`
|
283
|
+
#
|
284
|
+
# match_attribute(:type, other)
|
285
|
+
#
|
286
|
+
# @example selecting by block against an attribute; returns all nodes with
|
287
|
+
# `block.call(attribute(:type))` is true
|
288
|
+
#
|
289
|
+
# match_attribute(:type) { |value| value.starts_with? 'blah' }
|
290
|
+
#
|
291
|
+
# @example selecting by block against an attribute; returns all nodes with
|
292
|
+
# `block.call(attribute(:type)) == other` is true
|
293
|
+
#
|
294
|
+
# match_attribute(:type, 'moomin') { |value| value.downcase }
|
295
|
+
#
|
276
296
|
# @param name [#to_sym] an attribute name
|
277
|
-
# @param other [Object] an object to for equality with the
|
297
|
+
# @param other [Object] an object to check for equality with the
|
278
298
|
# values from the given attribute.
|
279
299
|
#
|
300
|
+
# @yield [value] yields each value with the attribute in name to the block
|
301
|
+
#
|
280
302
|
# @return [ValueArray] an array containing nodes for which the specified
|
281
|
-
# attribute has a value matching the given object
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
303
|
+
# attribute has a value matching the given attribute name, object, and
|
304
|
+
# block.
|
305
|
+
def match_attribute(name, other = nil, &block)
|
306
|
+
select(&compare_to_attribute(name, other, &block))
|
307
|
+
end
|
308
|
+
|
309
|
+
##
|
310
|
+
# @param name [#to_sym] an attribute name
|
311
|
+
# @param other [Object] an object to check for equality with the
|
312
|
+
# values from the given attribute.
|
313
|
+
#
|
314
|
+
# @yield [value] yields each value with the attribute in name to the block
|
315
|
+
#
|
316
|
+
# @return [ValueArray] an array containing nodes for which the specified
|
317
|
+
# attribute does not have a value matching the given attribute name,
|
318
|
+
# object, and block.
|
319
|
+
#
|
320
|
+
# @see #match_attribute for examples; this calls #reject, where it calls
|
321
|
+
# #select.
|
322
|
+
def reject_attribute(name, other = nil, &block)
|
323
|
+
reject(&compare_to_attribute(name, other, &block))
|
287
324
|
end
|
288
325
|
|
289
326
|
##
|
@@ -301,6 +338,20 @@ module Krikri
|
|
301
338
|
self.class.new(flat_map { |val| val[name] })
|
302
339
|
end
|
303
340
|
|
341
|
+
private
|
342
|
+
|
343
|
+
##
|
344
|
+
# @see #match_attribute, #reject_attribute
|
345
|
+
def compare_to_attribute(name, other, &block)
|
346
|
+
lambda do |v|
|
347
|
+
next unless v.attribute?(name.to_sym)
|
348
|
+
result = v.send(name)
|
349
|
+
result = yield(result) if block_given?
|
350
|
+
return result == other if other
|
351
|
+
result
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
304
355
|
public
|
305
356
|
|
306
357
|
class InvalidParserValueError < TypeError; end
|
data/lib/krikri/version.rb
CHANGED
data/lib/tasks/krikri.rake
CHANGED
@@ -27,12 +27,13 @@ namespace :krikri do
|
|
27
27
|
original_record = build(:oai_dc_record)
|
28
28
|
original_record.save unless original_record.exists?
|
29
29
|
|
30
|
-
|
31
|
-
provider
|
30
|
+
provider_uri = Krikri::Provider.base_uri + '123'
|
31
|
+
provider = Krikri::Provider.new(:rdf_subject => provider_uri).agent
|
32
|
+
provider.label = 'Moomin Valley Historical Society'
|
32
33
|
|
33
|
-
agg = build(:aggregation
|
34
|
-
|
35
|
-
|
34
|
+
agg = build(:aggregation,
|
35
|
+
:originalRecord => original_record.rdf_source,
|
36
|
+
:provider => provider)
|
36
37
|
|
37
38
|
agg.mint_id!('krikri_sample')
|
38
39
|
|
@@ -47,11 +48,15 @@ namespace :krikri do
|
|
47
48
|
original_record = build(:json_record)
|
48
49
|
original_record.save unless original_record.exists?
|
49
50
|
|
51
|
+
provider_uri = Krikri::Provider.base_uri + '456'
|
52
|
+
provider = Krikri::Provider.new(:rdf_subject => provider_uri).agent
|
53
|
+
provider.label = 'Snork Maiden Archives'
|
54
|
+
|
50
55
|
agg = build(:aggregation,
|
51
56
|
:originalRecord => ActiveTriples::Resource
|
52
57
|
.new(original_record.rdf_subject),
|
53
|
-
:sourceResource => build(:source_resource, title: nil)
|
54
|
-
|
58
|
+
:sourceResource => build(:source_resource, title: nil),
|
59
|
+
:provider => provider)
|
55
60
|
|
56
61
|
agg.mint_id!('krikri_sample_invalid')
|
57
62
|
|