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