audumbla 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 85d96776f960b63fce1a6e0533f8e53d9afe9ae8
4
+ data.tar.gz: c9fa438ae3c3ff6e6ae06395f188b18872b44a6b
5
+ SHA512:
6
+ metadata.gz: f409960eca0091c5405aecbdafb6dab5d1eaf1e3383ac23c3ac32a40a38b24210ec57f8456be9d4f949498537d4e2bc4b678551c836f121f8c255ddc9b627571
7
+ data.tar.gz: d0d5b93cad7e668c0faae99ad5dca370baa9d3e15d7d22becb917aa62acfb438428bd66b9f9ab29c79aececd376950b52b244ce26c0b5c623a6f018685626d66
@@ -0,0 +1,22 @@
1
+ Auðumbla
2
+ ========
3
+
4
+ [![Build Status](https://travis-ci.org/dpla/audumbla.svg?branch=develop)](https://travis-ci.org/dpla/audumbla)
5
+
6
+ Auðumbla provides the basic functionality for defining and running
7
+ metadata enrichments in [KriKri](https://github.com/dpla/KriKri).
8
+
9
+ Contribution Guidelines
10
+ -----------------------
11
+ Please observe the following guidelines:
12
+
13
+ - Write tests for your contributions.
14
+ - Document methods you add using YARD annotations.
15
+ - Follow the included style guidelines (i.e. run `rubocop` before committing).
16
+ - Use well formed commit messages.
17
+
18
+ Copyright & License
19
+ --------------------
20
+
21
+ - Copyright Digital Public Library of America, 2014-2015
22
+ - License: MIT
@@ -0,0 +1,4 @@
1
+ module Audumbla
2
+ autoload :Enrichment, 'audumbla/enrichment'
3
+ autoload :FieldEnrichment, 'audumbla/field_enrichment'
4
+ end
@@ -0,0 +1,4 @@
1
+ module Audumbla
2
+ autoload :Enrichment
3
+ autoload :FieldEnrichment
4
+ end
@@ -0,0 +1,148 @@
1
+ module Audumbla
2
+ ##
3
+ # Mixin module for enriching a set of input_fields and setting the resulting
4
+ # values to a set of output fields.
5
+ module Enrichment
6
+ ##
7
+ # The main enrichment method; passes specified input fields to
8
+ # #enrich_values, which must return an array of values with length equal to
9
+ # the number of output fields. The values of the output fields are set to
10
+ # the corresponding result from the enrichment.
11
+ #
12
+ # Pass fields to `input_fields` and `output_fields`. Fields are formatted
13
+ # as symbols in nested hashes, targeting a particular field in an
14
+ # ActiveTriples Resource property hierarchy:
15
+ #
16
+ # :sourceResource
17
+ # {:sourceResource => :spatial}
18
+ # {:sourceResource => {:creator => :name}}
19
+ #
20
+ # The record passed in is not altered, but cloned before the enrichment is
21
+ # applied. A common pattern may be:
22
+ #
23
+ # record = my_enrichment.enrich(record, input, output)
24
+ # record.persist!
25
+ #
26
+ # Input fields create an array selecting the values of all matching fields.
27
+ # For example:
28
+ #
29
+ # an array of values from record.sourceResource:
30
+ # :sourceResource
31
+ #
32
+ # an array of values combining spatial fields from the values of
33
+ # record.sourceResource:
34
+ # {:sourceResource => :spatial}
35
+ #
36
+ # an array of values combining name fields from the creators in
37
+ # record.sourceResource:
38
+ # {:sourceResource => {:creator => :name}}
39
+ #
40
+ #
41
+ # Output fields should be specified at a high enough level that the
42
+ # enrichment can build a complete value set from the input values provided.
43
+ # An enrichment for mapping names to LCSH URIs, that alters all creator
44
+ # fields might be formatted:
45
+ #
46
+ # my_enrichment.enrich(record,
47
+ # [{:sourceResource => {:creator => :providedLabel}}],
48
+ # [{:sourceResource => :creator}])
49
+ #
50
+ # This would pass the values like the following, sourced from the
51
+ # providedLabel, to #enrich_value:
52
+ #
53
+ # [['Moomintroll', 'Moomin Papa', 'Moomin Mama']]
54
+ #
55
+ # And it would expect to receive an array of values set directly to creator,
56
+ # overwriting all existing creator values:
57
+ #
58
+ # [DPLA::MAP::Agent:0x3ff(default),
59
+ # DPLA::MAP::Agent:0x9f5(default),
60
+ # DPLA::MAP::Agent:0x3a8(default)]
61
+ #
62
+ # @param record [ActiveTriples::Resource] the record to enrich
63
+ # @param input_fields [Array] the fields whose values to pass to the
64
+ # enrichment method
65
+ # @param output_fields [Array] the fields on which to apply the enrichment
66
+ # @return [ActiveTriples::Resource] the enriched record
67
+ def enrich(record, input_fields, output_fields)
68
+ enrich!(record.clone, input_fields, output_fields)
69
+ end
70
+
71
+ ##
72
+ # Runs the enrichment directly on the given record.
73
+ #
74
+ # @see Audumbla::Enrichment#enrich
75
+ def enrich!(record, input_fields, output_fields)
76
+ output_fields.map! { |f| field_to_chain(f) }
77
+
78
+ values = values_from_fields(record, input_fields)
79
+ values = enrich_value(values).dup
80
+
81
+ raise 'field/value mismatch.' \
82
+ "#{values.count} values for #{output_fields.count} fields." unless
83
+ values.count == output_fields.count
84
+
85
+ output_fields.each { |field| set_field(record, field, values.shift) }
86
+ record
87
+ end
88
+
89
+ ##
90
+ # @abstract Runs the enrichment against a field
91
+ #
92
+ # Accept an array of values from an ActiveTriples::Resource property, and
93
+ # return an array of values to set to output fields.
94
+ #
95
+ # @param [ActiveTriples::Resource, RDF::Literal] the value(s) to process
96
+ # @return [ActiveTriples::Resource] the enriched record
97
+ def enrich_value(_)
98
+ raise NotImplementedError
99
+ end
100
+
101
+ def list_fields(record)
102
+ fields = []
103
+ record.class.properties.each do |prop, _|
104
+ fields << prop.to_sym
105
+
106
+ objs = resources(record.send(fields.last)).map { |r| list_fields(r) }
107
+ next if objs.empty?
108
+
109
+ objs.flatten.each { |obj| fields << { prop => obj } }
110
+ end
111
+ fields
112
+ end
113
+
114
+ private
115
+
116
+ def values_for_field(record, field_chain)
117
+ values = record.send(field_chain.first)
118
+ return values if field_chain.length == 1
119
+ resources(values).map { |v| values_for_field(v, field_chain[1..-1]) }
120
+ .flatten.compact
121
+ end
122
+
123
+ def set_field(record, field_chain, values)
124
+ field = field_chain.pop
125
+ return record.send("#{field}=".to_sym, values) if field_chain.length == 0
126
+ values_for_field(record, field_chain).each do |obj|
127
+ obj.send("#{field}=".to_sym, values)
128
+ end
129
+ end
130
+
131
+ def resources(values)
132
+ values.select { |v| v.is_a? ActiveTriples::Resource }
133
+ end
134
+
135
+ def literals(values)
136
+ values.select { |v| !v.is_a?(ActiveTriples::Resource) }
137
+ end
138
+
139
+ def field_to_chain(field)
140
+ return Array(field) if field.is_a? Symbol
141
+ [field.keys.first, field_to_chain(field.values.first)].flatten
142
+ end
143
+
144
+ def values_from_fields(record, input_fields)
145
+ input_fields.map { |f| values_for_field(record, field_to_chain(f)) }
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,148 @@
1
+ module Audumbla
2
+ ##
3
+ # Mixin module for enriching a set of input_fields and setting the resulting
4
+ # values to a set of output fields.
5
+ module Enrichment
6
+ ##
7
+ # The main enrichment method; passes specified input fields to
8
+ # #enrich_values, which must return an array of values with length equal to
9
+ # the number of output fields. The values of the output fields are set to
10
+ # the corresponding result from the enrichment.
11
+ #
12
+ # Pass fields to `input_fields` and `output_fields`. Fields are formatted
13
+ # as symbols in nested hashes, targeting a particular field in an
14
+ # ActiveTriples Resource property hierarchy:
15
+ #
16
+ # :sourceResource
17
+ # {:sourceResource => :spatial}
18
+ # {:sourceResource => {:creator => :name}}
19
+ #
20
+ # The record passed in is not altered, but cloned before the enrichment is
21
+ # applied. A common pattern may be:
22
+ #
23
+ # record = my_enrichment.enrich(record, input, output)
24
+ # record.persist!
25
+ #
26
+ # Input fields create an array selecting the values of all matching fields.
27
+ # For example:
28
+ #
29
+ # an array of values from record.sourceResource:
30
+ # :sourceResource
31
+ #
32
+ # an array of values combining spatial fields from the values of
33
+ # record.sourceResource:
34
+ # {:sourceResource => :spatial}
35
+ #
36
+ # an array of values combining name fields from the creators in
37
+ # record.sourceResource:
38
+ # {:sourceResource => {:creator => :name}}
39
+ #
40
+ #
41
+ # Output fields should be specified at a high enough level that the
42
+ # enrichment can build a complete value set from the input values provided.
43
+ # An enrichment for mapping names to LCSH URIs, that alters all creator
44
+ # fields might be formatted:
45
+ #
46
+ # my_enrichment.enrich(record,
47
+ # [{:sourceResource => {:creator => :providedLabel}}],
48
+ # [{:sourceResource => :creator}])
49
+ #
50
+ # This would pass the values like the following, sourced from the
51
+ # providedLabel, to #enrich_value:
52
+ #
53
+ # [['Moomintroll', 'Moomin Papa', 'Moomin Mama']]
54
+ #
55
+ # And it would expect to receive an array of values set directly to creator,
56
+ # overwriting all existing creator values:
57
+ #
58
+ # [DPLA::MAP::Agent:0x3ff(default),
59
+ # DPLA::MAP::Agent:0x9f5(default),
60
+ # DPLA::MAP::Agent:0x3a8(default)]
61
+ #
62
+ # @param record [ActiveTriples::Resource] the record to enrich
63
+ # @param input_fields [Array] the fields whose values to pass to the
64
+ # enrichment method
65
+ # @param output_fields [Array] the fields on which to apply the enrichment
66
+ # @return [ActiveTriples::Resource] the enriched record
67
+ def enrich(record, input_fields, output_fields)
68
+ enrich!(record.clone, input_fields, output_fields)
69
+ end
70
+
71
+ ##
72
+ # Runs the enrichment directly on the given record.
73
+ #
74
+ # @see Krikri::Enrichment#enrich
75
+ def enrich!(record, input_fields, output_fields)
76
+ output_fields.map! { |f| field_to_chain(f) }
77
+
78
+ values = values_from_fields(record, input_fields)
79
+ values = enrich_value(values).dup
80
+
81
+ raise 'field/value mismatch.' \
82
+ "#{values.count} values for #{output_fields.count} fields." unless
83
+ values.count == output_fields.count
84
+
85
+ output_fields.each { |field| set_field(record, field, values.shift) }
86
+ record
87
+ end
88
+
89
+ ##
90
+ # @abstract Runs the enrichment against a field
91
+ #
92
+ # Accept an array of values from an ActiveTriples::Resource property, and
93
+ # return an array of values to set to output fields.
94
+ #
95
+ # @param [ActiveTriples::Resource, RDF::Literal] the value(s) to process
96
+ # @return [ActiveTriples::Resource] the enriched record
97
+ def enrich_value(_)
98
+ raise NotImplementedError
99
+ end
100
+
101
+ def list_fields(record)
102
+ fields = []
103
+ record.class.properties.each do |prop, _|
104
+ fields << prop.to_sym
105
+
106
+ objs = resources(record.send(fields.last)).map { |r| list_fields(r) }
107
+ next if objs.empty?
108
+
109
+ objs.flatten.each { |obj| fields << { prop => obj } }
110
+ end
111
+ fields
112
+ end
113
+
114
+ private
115
+
116
+ def values_for_field(record, field_chain)
117
+ values = record.send(field_chain.first)
118
+ return values if field_chain.length == 1
119
+ resources(values).map { |v| values_for_field(v, field_chain[1..-1]) }
120
+ .flatten.compact
121
+ end
122
+
123
+ def set_field(record, field_chain, values)
124
+ field = field_chain.pop
125
+ return record.send("#{field}=".to_sym, values) if field_chain.length == 0
126
+ values_for_field(record, field_chain).each do |obj|
127
+ obj.send("#{field}=".to_sym, values)
128
+ end
129
+ end
130
+
131
+ def resources(values)
132
+ values.select { |v| v.is_a? ActiveTriples::Resource }
133
+ end
134
+
135
+ def literals(values)
136
+ values.select { |v| !v.is_a?(ActiveTriples::Resource) }
137
+ end
138
+
139
+ def field_to_chain(field)
140
+ return Array(field) if field.is_a? Symbol
141
+ [field.keys.first, field_to_chain(field.values.first)].flatten
142
+ end
143
+
144
+ def values_from_fields(record, input_fields)
145
+ input_fields.map { |f| values_for_field(record, field_to_chain(f)) }
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,4 @@
1
+ module Audumbla
2
+ module Enrichments
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Krikri
2
+ autoload :Enrichment, 'krikri/enrichment'
3
+ autoload :FieldEnrichment, 'krikri/field_enrichment'
4
+
5
+ module Enrichments
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Krikri::Enrichments
2
+ ##
3
+ #
4
+ class Geocode
5
+ include Krikri::FieldEnrichment
6
+
7
+ def enrich_value(value)
8
+ value
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Krikri
2
+ module Enrichments
3
+ VERSION = '0.0.1'.final
4
+ end
5
+ end
@@ -0,0 +1,60 @@
1
+ module Audumbla
2
+ ##
3
+ # Enrich a specific field or list of fields, setting the property to the
4
+ # supplied value
5
+ module FieldEnrichment
6
+ include Enrichment
7
+
8
+ ##
9
+ # The main enrichment method; runs the enrichment against a stated
10
+ # set of fields for a record.
11
+ #
12
+ # This is a narrower case of `Audumbla::Enrichment` which runs the
13
+ # enrichment against each of the specified fields in turn, setting
14
+ # the field's value to the result.
15
+ #
16
+ # For example:
17
+ #
18
+ # delete_empty_string_literals.enrich(record,
19
+ # {:sourceResource => {:creator => :name}})
20
+ #
21
+ # To apply the enrichment across all fields, leave the fields parameter
22
+ # empty, or use `:all`:
23
+ #
24
+ # delete_empty_string_literals.enrich(record)
25
+ # delete_empty_string_literals.enrich(record, :all)
26
+ #
27
+ # @see Audumbla::Enrichment#enrich for documentation about field
28
+ # formatting
29
+ #
30
+ # @param record [ActiveTriples::Resource] the record to enrich
31
+ # @param fields [Array] the fields on which to apply the enrichment
32
+ # @return [ActiveTriples::Resource] the enriched record
33
+ def enrich(record, *fields)
34
+ record = record.clone
35
+ return enrich_all(record) if fields.empty? || fields == [:all]
36
+ fields.each { |f| enrich_field(record, field_to_chain(f)) }
37
+ record
38
+ end
39
+
40
+ def enrich_field(record, field_chain)
41
+ field = field_chain.first
42
+ return record unless record.respond_to? field
43
+ values = record.send(field)
44
+ if field_chain.length == 1
45
+ new_values = values.map { |v| enrich_value(v) }.flatten.compact
46
+ record.send("#{field}=".to_sym, new_values)
47
+ else
48
+ resources(values).each { |v| enrich_field(v, field_chain[1..-1]) }
49
+ end
50
+ record
51
+ end
52
+
53
+ def enrich_all(record)
54
+ list_fields(record).each do |field|
55
+ enrich_field(record, field_to_chain(field))
56
+ end
57
+ record
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,60 @@
1
+ module Krikri
2
+ ##
3
+ # Enrich a specific field or list of fields, setting the property to the
4
+ # supplied value
5
+ module FieldEnrichment
6
+ include Enrichment
7
+
8
+ ##
9
+ # The main enrichment method; runs the enrichment against a stated
10
+ # set of fields for a record.
11
+ #
12
+ # This is a narrower case of `Krikri::Enrichment` which runs the
13
+ # enrichment against each of the specified fields in turn, setting
14
+ # the field's value to the result.
15
+ #
16
+ # For example:
17
+ #
18
+ # delete_empty_string_literals.enrich(record,
19
+ # {:sourceResource => {:creator => :name}})
20
+ #
21
+ # To apply the enrichment across all fields, leave the fields parameter
22
+ # empty, or use `:all`:
23
+ #
24
+ # delete_empty_string_literals.enrich(record)
25
+ # delete_empty_string_literals.enrich(record, :all)
26
+ #
27
+ # @see Krikri::Enrichment#enrich for documentation about field
28
+ # formatting
29
+ #
30
+ # @param record [ActiveTriples::Resource] the record to enrich
31
+ # @param fields [Array] the fields on which to apply the enrichment
32
+ # @return [ActiveTriples::Resource] the enriched record
33
+ def enrich(record, *fields)
34
+ record = record.clone
35
+ return enrich_all(record) if fields.empty? || fields == [:all]
36
+ fields.each { |f| enrich_field(record, field_to_chain(f)) }
37
+ record
38
+ end
39
+
40
+ def enrich_field(record, field_chain)
41
+ field = field_chain.first
42
+ return record unless record.respond_to? field
43
+ values = record.send(field)
44
+ if field_chain.length == 1
45
+ new_values = values.map { |v| enrich_value(v) }.flatten.compact
46
+ record.send("#{field}=".to_sym, new_values)
47
+ else
48
+ resources(values).each { |v| enrich_field(v, field_chain[1..-1]) }
49
+ end
50
+ record
51
+ end
52
+
53
+ def enrich_all(record)
54
+ list_fields(record).each do |field|
55
+ enrich_field(record, field_to_chain(field))
56
+ end
57
+ record
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,242 @@
1
+ shared_context 'with record' do
2
+ let(:record) { build(:aggregation) }
3
+ end
4
+
5
+ shared_examples 'an enrichment' do
6
+ include_context 'with record'
7
+
8
+ it { is_expected.to be_a Audumbla::Enrichment }
9
+ it { is_expected.to respond_to :enrich_value }
10
+
11
+ describe '#list_fields' do
12
+ let(:list) { subject.list_fields(record) }
13
+
14
+ it 'generates a list of fields' do
15
+ expect(list).to include(an_instance_of(Symbol), an_instance_of(Hash))
16
+ end
17
+ end
18
+
19
+ describe '#enrich' do
20
+ before { allow(subject).to receive(:enrich_value).and_return(new_value) }
21
+
22
+ let(:new_value) { ['Christmas in Moominvalley'] }
23
+ let(:args) do
24
+ subject.class.instance_method(:enrich).arity > 1 ? enrich_args : [record]
25
+ end
26
+
27
+ it 'returns a record eql to the input record' do
28
+ expect(subject.enrich(*args)).to eq record
29
+ end
30
+
31
+ it 'copies the input record' do
32
+ expect(subject.enrich(*args)).not_to eql record
33
+ end
34
+
35
+ it 'does not change the record object passed in' do
36
+ expect { subject.enrich(*args) }.not_to change { record }
37
+ end
38
+ end
39
+ end
40
+
41
+ shared_examples 'a generic enrichment' do
42
+ it_behaves_like 'an enrichment'
43
+ include_context 'with record'
44
+
45
+ let(:enrich_args) do
46
+ [record, [{ :sourceResource => :title }], [{ :sourceResource => :creator }]]
47
+ end
48
+
49
+ describe '#enrich' do
50
+ before do
51
+ allow(subject).to receive(:enrich_value).and_return(new_value)
52
+ end
53
+
54
+ shared_examples 'multiple input fields' do
55
+ before do
56
+ record.sourceResource.first.spatial.first.name = 'NY'
57
+ enrich_args[1] << { :sourceResource => { :spatial => :name } }
58
+ end
59
+
60
+ let(:input_values) do
61
+ [record.sourceResource.map(&:title).flatten,
62
+ record.sourceResource.map { |sr| sr.spatial.map(&:name) }.flatten]
63
+ end
64
+
65
+ it 'enriches with values for input fields' do
66
+ expect(subject).to receive(:enrich_value).with(input_values)
67
+ subject.enrich(*enrich_args)
68
+ end
69
+ end
70
+
71
+ context 'with single output field' do
72
+ include_examples 'multiple input fields'
73
+
74
+ let(:new_value) { ['snufkin'] }
75
+
76
+ it 'enriches targeted field' do
77
+ subject.enrich(*enrich_args).sourceResource.map do |cho|
78
+ expect(cho.creator).to eq new_value
79
+ end
80
+ end
81
+ end
82
+
83
+ context 'with multiple output fields' do
84
+ include_examples 'multiple input fields'
85
+
86
+ before do
87
+ enrich_args[2] << { :sourceResource => :spatial }
88
+ end
89
+
90
+ let(:new_value) { [['snufkin'], ['moominvalley']] }
91
+
92
+ it 'enriches targeted fields' do
93
+ subject.enrich(*enrich_args).sourceResource.map do |cho|
94
+ expect(cho.creator).to eq new_value.first
95
+ expect(cho.spatial).to eq new_value[1]
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ shared_examples 'a field enrichment' do
103
+ it_behaves_like 'an enrichment'
104
+ include_context 'with record'
105
+
106
+ let(:updated_value) { 'Christmas in Moominvalley' }
107
+
108
+ describe '#enrich_field' do
109
+ let(:field_chain) { [:sourceResource, :creator, :providedLabel] }
110
+ let(:klass) { record.sourceResource.first.creator.first.class }
111
+ let(:enriched) { subject.enrich_field(record, field_chain) }
112
+
113
+ before do
114
+ allow(subject).to receive(:enrich_value).and_return(updated_value)
115
+ end
116
+
117
+ it 'updates value with enriched version' do
118
+ expect(enriched.sourceResource.first.creator.first.providedLabel)
119
+ .to eq [updated_value]
120
+ end
121
+
122
+ context 'when targeted value is empty' do
123
+ before do
124
+ enriched.sourceResource.first.creator.first.providedLabel = nil
125
+ end
126
+
127
+ it 'passes over value' do
128
+ expect(enriched.sourceResource.first.creator.first.providedLabel)
129
+ .to eq []
130
+ end
131
+ end
132
+
133
+ context 'with multiple values' do
134
+ before do
135
+ new_creator = klass.new
136
+ new_creator.providedLabel = 'old value'
137
+ record.sourceResource.first.creator << new_creator
138
+ record.sourceResource.first.creator << 'literal value'
139
+ end
140
+
141
+ it 'retains literal values' do
142
+ expect(enriched.sourceResource.first.creator)
143
+ .to contain_exactly('literal value',
144
+ an_instance_of(klass),
145
+ an_instance_of(klass))
146
+ end
147
+
148
+ it 'updates values with enriched versions' do
149
+ creators = enriched.sourceResource.first.creator.select do |o|
150
+ o.is_a?(klass)
151
+ end
152
+ creators.each { |val| expect(val.providedLabel).to eq [updated_value] }
153
+ end
154
+
155
+ context 'when node is missing property' do
156
+ before do
157
+ record.sourceResource.first.creator << node
158
+ end
159
+
160
+ let(:node) do
161
+ creator = ActiveTriples::Resource.new
162
+ creator.set_value(RDF::DC.title, 'moomin')
163
+ creator
164
+ end
165
+
166
+ it 'leaves node unaltered' do
167
+ expect(record.sourceResource.first.creator).to include node
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ describe '#enrich_all' do
174
+ it 'runs enrichment over all fields' do
175
+ expect(subject).to receive(:enrich_field)
176
+ .exactly(subject.list_fields(record).count).times
177
+ subject.enrich_all(record)
178
+ end
179
+
180
+ it 'sets fields to new value' do
181
+ allow(subject).to receive(:enrich_value).and_return(updated_value)
182
+ subject.enrich_all(record)
183
+ record.class.properties.each do |prop, _|
184
+ expect(record.send(prop)).to eq [updated_value]
185
+ end
186
+ end
187
+
188
+ it 'returns the record' do
189
+ expect(subject.enrich_all(record)).to eq record
190
+ end
191
+ end
192
+
193
+ describe 'enrich' do
194
+ it 'defaults to all fields' do
195
+ expect(subject).to receive(:enrich_all)
196
+ subject.enrich(record)
197
+ end
198
+
199
+ it 'accepts :all for fields' do
200
+ expect(subject).to receive(:enrich_all)
201
+ subject.enrich(record, :all)
202
+ end
203
+
204
+ context 'with field arguments' do
205
+ let(:simple_field) { :preview }
206
+ let(:deep_field) do
207
+ { :sourceResource => { :creator => :providedLabel } }
208
+ end
209
+ let(:deep_field_2) do
210
+ { :sourceResource => { :spatial => :parentFeature } }
211
+ end
212
+
213
+ let(:deep_field_chain) { [:sourceResource, :creator, :providedLabel] }
214
+ let(:deep_field_2_chain) { [:sourceResource, :spatial, :parentFeature] }
215
+
216
+ it 'runs against simple fields' do
217
+ expect(subject).to receive(:enrich_field).with(record, [simple_field])
218
+ subject.enrich(record, simple_field)
219
+ end
220
+
221
+ it 'runs against deep fields' do
222
+ expect(subject).to receive(:enrich_field).with(record, deep_field_chain)
223
+ subject.enrich(record, deep_field)
224
+ end
225
+
226
+ it 'runs against multiple fields' do
227
+ expect(subject).to receive(:enrich_field).with(record, [simple_field])
228
+ expect(subject).to receive(:enrich_field).with(record, deep_field_chain)
229
+ expect(subject).to receive(:enrich_field)
230
+ .with(record, deep_field_2_chain)
231
+ subject.enrich(record, simple_field, deep_field, deep_field_2)
232
+ end
233
+
234
+ it 'is a copy of the input record' do
235
+ expect(subject.enrich(record, simple_field, deep_field, deep_field_2))
236
+ .to eq record
237
+ expect(subject.enrich(record, simple_field, deep_field, deep_field_2))
238
+ .not_to eql record
239
+ end
240
+ end
241
+ end
242
+ end
@@ -0,0 +1,3 @@
1
+ module Audumbla
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,5 @@
1
+ module Krikri
2
+ module Enrichments
3
+ VERSION = '0.0.1'.freeze
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Audumbla::Enrichment do
4
+ subject { klass.new }
5
+
6
+ let(:klass) { Class.new { include Audumbla::Enrichment } }
7
+
8
+ it_behaves_like 'a generic enrichment'
9
+
10
+ describe '#enrich_value' do
11
+ it 'is abstract' do
12
+ expect { subject.enrich_value(nil) }.to raise_error NotImplementedError
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Krikri::Enrichment do
4
+ subject { klass.new }
5
+
6
+ let(:klass) { Class.new { include Krikri::Enrichment } }
7
+
8
+ it_behaves_like 'a generic enrichment'
9
+
10
+ describe '#enrich_value' do
11
+ it 'is abstract' do
12
+ expect { subject.enrich_value(nil) }.to raise_error NotImplementedError
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Krikri::Enrichments::Geocode do
4
+ it_behaves_like 'a field enrichment'
5
+
6
+ it '' do
7
+ require 'pry'
8
+ binding.pry
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Audumbla::FieldEnrichment do
4
+ subject { enrichment_class.new }
5
+
6
+ let(:enrichment_class) { Class.new { include Audumbla::FieldEnrichment } }
7
+
8
+ context 'with implementation' do
9
+ before { allow(subject).to receive(:enrich_value).and_return('moomin') }
10
+
11
+ it_behaves_like 'a field enrichment'
12
+ end
13
+
14
+ describe '#enrich_value' do
15
+ it 'is abstract' do
16
+ expect { subject.enrich_value(nil) }.to raise_error NotImplementedError
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Krikri::FieldEnrichment do
4
+ subject { enrichment_class.new }
5
+
6
+ let(:enrichment_class) { Class.new { include Krikri::FieldEnrichment } }
7
+
8
+ context 'with implementation' do
9
+ before { allow(subject).to receive(:enrich_value).and_return('moomin') }
10
+
11
+ it_behaves_like 'a field enrichment'
12
+ end
13
+
14
+ describe '#enrich_value' do
15
+ it 'is abstract' do
16
+ expect { subject.enrich_value(nil) }.to raise_error NotImplementedError
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'audumbla'
2
+ require 'audumbla/spec/enrichment'
3
+
4
+ if ENV['COVERAGE'] == 'yes'
5
+ require 'simplecov'
6
+ SimpleCov.start
7
+ end
8
+
9
+ require 'codeclimate-test-reporter'
10
+ CodeClimate::TestReporter.start
11
+
12
+ require 'rspec'
13
+ require 'factory_girl'
14
+ require 'dpla/map/factories'
15
+
16
+ RSpec.configure do |config|
17
+ config.color = true
18
+ config.formatter = :progress
19
+ config.mock_with :rspec
20
+
21
+ config.include FactoryGirl::Syntax::Methods
22
+
23
+ config.order = 'random'
24
+ end
@@ -0,0 +1,23 @@
1
+ if ENV['COVERAGE'] == 'yes'
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'codeclimate-test-reporter'
7
+ CodeClimate::TestReporter.start
8
+
9
+ require 'rspec'
10
+ require 'factory_girl'
11
+
12
+ # Load support files
13
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
14
+
15
+ RSpec.configure do |config|
16
+ config.color = true
17
+ config.formatter = :progress
18
+ config.mock_with :rspec
19
+
20
+ config.include FactoryGirl::Syntax::Methods
21
+
22
+ config.order = 'random'
23
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audumbla
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Audrey Altman
8
+ - Mark Breedlove
9
+ - Tom Johnson
10
+ - Mark Matienzo
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2015-05-29 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: dpla-map
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: 4.0.0.0.pre.10
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 4.0.0.0.pre.10
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: '3.0'
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '3.0'
44
+ - !ruby/object:Gem::Dependency
45
+ name: pry
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 0.10.0
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 0.10.0
58
+ description: Metadata enrichment for cultural heritage institutions.
59
+ email:
60
+ - tech@dp.la
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - README.md
66
+ - lib/audumbla.rb
67
+ - lib/audumbla.rb~
68
+ - lib/audumbla/enrichment.rb
69
+ - lib/audumbla/enrichment.rb~
70
+ - lib/audumbla/enrichments.rb
71
+ - lib/audumbla/enrichments.rb~
72
+ - lib/audumbla/enrichments/geocode.rb~
73
+ - lib/audumbla/enrichments/version.rb~
74
+ - lib/audumbla/field_enrichment.rb
75
+ - lib/audumbla/field_enrichment.rb~
76
+ - lib/audumbla/spec/enrichment.rb
77
+ - lib/audumbla/version.rb
78
+ - lib/audumbla/version.rb~
79
+ - spec/lib/audumbla/enrichment_spec.rb
80
+ - spec/lib/audumbla/enrichment_spec.rb~
81
+ - spec/lib/audumbla/enrichments/geocode_spec.rb~
82
+ - spec/lib/audumbla/field_enrichment_spec.rb
83
+ - spec/lib/audumbla/field_enrichment_spec.rb~
84
+ - spec/spec_helper.rb
85
+ - spec/spec_helper.rb~
86
+ homepage: http://github.com/dpla/audumbla
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.2.1
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: A toolkit for enhancement of RDF Metadata
110
+ test_files:
111
+ - spec/lib/audumbla/enrichment_spec.rb
112
+ - spec/lib/audumbla/field_enrichment_spec.rb
113
+ - spec/lib/audumbla/field_enrichment_spec.rb~
114
+ - spec/lib/audumbla/enrichment_spec.rb~
115
+ - spec/lib/audumbla/enrichments/geocode_spec.rb~
116
+ - spec/spec_helper.rb
117
+ - spec/spec_helper.rb~
118
+ has_rdoc: