audumbla 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: