nokogiri-happymapper 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +4 -0
- data/lib/happymapper.rb +2 -0
- data/lib/happymapper/element.rb +2 -0
- data/lib/happymapper/supported_types.rb +2 -4
- data/lib/happymapper/version.rb +1 -1
- data/lib/nokogiri-happymapper.rb +4 -0
- data/spec/features/after_parse_callbacks_spec.rb +6 -3
- data/spec/features/attribute_default_value_spec.rb +5 -6
- data/spec/features/attributes_spec.rb +1 -1
- data/spec/features/has_many_empty_array_spec.rb +1 -1
- data/spec/features/ignay_spec.rb +21 -11
- data/spec/features/inheritance_spec.rb +27 -19
- data/spec/features/mixed_namespaces_spec.rb +1 -1
- data/spec/features/parse_with_object_to_update_spec.rb +19 -13
- data/spec/features/same_tag_different_meaning_spec.rb +1 -1
- data/spec/features/to_xml_spec.rb +21 -18
- data/spec/features/to_xml_with_namespaces_spec.rb +19 -16
- data/spec/features/wildcard_tag_name_spec.rb +26 -16
- data/spec/features/wrap_spec.rb +27 -22
- data/spec/features/xpath_spec.rb +1 -1
- data/spec/happymapper/item_spec.rb +5 -2
- data/spec/happymapper_spec.rb +257 -180
- data/spec/spec_helper.rb +1 -1
- metadata +4 -8
- data/spec/happymapper/element_spec.rb +0 -11
- data/spec/happymapper/text_node_spec.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29c4973fa94bd305d925426e58d62690a2929c57af50a2e9d1666957b030db0c
|
4
|
+
data.tar.gz: e93f66003fc2991d3a28acf775d4224e2d2184751d082e48393c371580949803
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ecf514caadcbce076cafe31127cc3a108a004b7abc75e3bfe2aa18c3d22f1fc86294c5912e43cb30f6d89b26021199d6a8e1cb3f9f63d331ba8eb4afcb2ee2f
|
7
|
+
data.tar.gz: 3811e5811bc2205708e038629155a195cb949c41f11d096c13db991251d939c1e2327c8c1f80b6e5aab4783ca71f898f06ab3adaa5c20e66e57b90adce634880
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -32,6 +32,10 @@ Or add the `nokogiri-happymapper` gem to your project's `Gemfile`.
|
|
32
32
|
|
33
33
|
gem 'nokogiri-happymapper', require: 'happymapper'
|
34
34
|
|
35
|
+
You can now also require `nokogiri-happymapper` directly.
|
36
|
+
|
37
|
+
gem 'nokogiri-happymapper'
|
38
|
+
|
35
39
|
Run Bundler to install the gem:
|
36
40
|
|
37
41
|
$ bundle install
|
data/lib/happymapper.rb
CHANGED
@@ -405,6 +405,7 @@ module HappyMapper
|
|
405
405
|
end
|
406
406
|
if namespace
|
407
407
|
return [] unless namespaces.find { |name, _url| ["xmlns:#{namespace}", namespace].include? name }
|
408
|
+
|
408
409
|
xpath += "#{namespace}:"
|
409
410
|
end
|
410
411
|
|
@@ -674,6 +675,7 @@ module HappyMapper
|
|
674
675
|
#
|
675
676
|
def register_namespaces_with_builder(builder)
|
676
677
|
return unless self.class.instance_variable_get('@registered_namespaces')
|
678
|
+
|
677
679
|
self.class.instance_variable_get('@registered_namespaces').sort.each do |name, href|
|
678
680
|
name = nil if name == 'xmlns'
|
679
681
|
builder.doc.root.add_namespace(name, href)
|
data/lib/happymapper/element.rb
CHANGED
@@ -34,11 +34,13 @@ module HappyMapper
|
|
34
34
|
|
35
35
|
def handle_attributes_option(result, value, xpath_options)
|
36
36
|
return unless options[:attributes].is_a?(Hash)
|
37
|
+
|
37
38
|
result = result.first unless result.respond_to?(:attribute_nodes)
|
38
39
|
return unless result.respond_to?(:attribute_nodes)
|
39
40
|
|
40
41
|
result.attribute_nodes.each do |xml_attribute|
|
41
42
|
next unless (attribute_options = options[:attributes][xml_attribute.name.to_sym])
|
43
|
+
|
42
44
|
attribute_value = Attribute.new(xml_attribute.name.to_sym, *attribute_options).
|
43
45
|
from_xml_node(result, namespace, xpath_options)
|
44
46
|
|
@@ -110,14 +110,12 @@ module HappyMapper
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
# rubocop:disable Style/DateTime
|
114
113
|
register_type DateTime do |value|
|
115
|
-
DateTime.parse(value.to_s) if value && !value.empty?
|
114
|
+
DateTime.parse(value.to_s, true, Date::ITALY) if value && !value.empty?
|
116
115
|
end
|
117
|
-
# rubocop:enable Style/DateTime
|
118
116
|
|
119
117
|
register_type Date do |value|
|
120
|
-
Date.parse(value.to_s) if value && !value.empty?
|
118
|
+
Date.parse(value.to_s, true, Date::ITALY) if value && !value.empty?
|
121
119
|
end
|
122
120
|
|
123
121
|
register_type Boolean do |value|
|
data/lib/happymapper/version.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
RSpec.describe 'after_parse callbacks' do
|
5
|
+
RSpec.describe 'after_parse callbacks', type: :feature do
|
6
6
|
module AfterParseSpec
|
7
7
|
class Address
|
8
8
|
include HappyMapper
|
@@ -23,7 +23,10 @@ RSpec.describe 'after_parse callbacks' do
|
|
23
23
|
AfterParseSpec::Address.after_parse(&cb2)
|
24
24
|
|
25
25
|
object = AfterParseSpec::Address.parse fixture_file('address.xml')
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
aggregate_failures do
|
28
|
+
expect(from_cb).to eq(object)
|
29
|
+
expect(called).to eq(true)
|
30
|
+
end
|
28
31
|
end
|
29
32
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'Attribute Default Value' do
|
5
|
+
RSpec.describe 'Attribute Default Value', type: :feature do
|
6
6
|
context 'when given a default value' do
|
7
7
|
class Meal
|
8
8
|
include HappyMapper
|
@@ -10,12 +10,11 @@ describe 'Attribute Default Value' do
|
|
10
10
|
attribute :type, String, default: 'omnivore'
|
11
11
|
end
|
12
12
|
|
13
|
-
let(:subject) { Meal }
|
14
13
|
let(:default_meal_type) { 'omnivore' }
|
15
14
|
|
16
15
|
context 'when no value has been specified' do
|
17
16
|
it 'returns the default value' do
|
18
|
-
meal =
|
17
|
+
meal = Meal.parse('<meal />')
|
19
18
|
expect(meal.type).to eq default_meal_type
|
20
19
|
end
|
21
20
|
end
|
@@ -24,7 +23,7 @@ describe 'Attribute Default Value' do
|
|
24
23
|
let(:expected_xml) { %(<?xml version="1.0"?>\n<meal/>\n) }
|
25
24
|
|
26
25
|
it 'the default value is not included' do
|
27
|
-
meal =
|
26
|
+
meal = Meal.new
|
28
27
|
expect(meal.to_xml).to eq expected_xml
|
29
28
|
end
|
30
29
|
end
|
@@ -33,14 +32,14 @@ describe 'Attribute Default Value' do
|
|
33
32
|
let(:expected_xml) { %(<?xml version="1.0"?>\n<meal type="kosher"/>\n) }
|
34
33
|
|
35
34
|
it 'returns the new value' do
|
36
|
-
meal =
|
35
|
+
meal = Meal.parse('<meal />')
|
37
36
|
meal.type = 'vegan'
|
38
37
|
|
39
38
|
expect(meal.type).not_to eq default_meal_type
|
40
39
|
end
|
41
40
|
|
42
41
|
it 'saves the new value to the xml' do
|
43
|
-
meal =
|
42
|
+
meal = Meal.new
|
44
43
|
meal.type = 'kosher'
|
45
44
|
expect(meal.to_xml).to eq expected_xml
|
46
45
|
end
|
data/spec/features/ignay_spec.rb
CHANGED
@@ -38,7 +38,7 @@ class CatalogNode
|
|
38
38
|
has_many :nodes, CatalogNode, tag: 'Node', xpath: 'child::*'
|
39
39
|
end
|
40
40
|
|
41
|
-
describe
|
41
|
+
RSpec.describe 'parsing a VOD catalog', type: :feature do
|
42
42
|
let(:catalog_tree) { CatalogTree.parse(fixture_file('inagy.xml'), single: true) }
|
43
43
|
|
44
44
|
it 'is not nil' do
|
@@ -50,11 +50,15 @@ describe HappyMapper do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'has many nodes' do
|
53
|
-
|
54
|
-
|
53
|
+
nodes = catalog_tree.nodes
|
54
|
+
|
55
|
+
aggregate_failures do
|
56
|
+
expect(nodes).not_to be_empty
|
57
|
+
expect(nodes.length).to eq(2)
|
58
|
+
end
|
55
59
|
end
|
56
60
|
|
57
|
-
|
61
|
+
describe 'first node' do
|
58
62
|
let(:first_node) { catalog_tree.nodes.first }
|
59
63
|
|
60
64
|
it 'has a name' do
|
@@ -62,17 +66,23 @@ describe HappyMapper do
|
|
62
66
|
end
|
63
67
|
|
64
68
|
it 'has translations' do
|
65
|
-
|
69
|
+
translations = first_node.translations
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
aggregate_failures do
|
72
|
+
expect(translations.length).to eq(2)
|
73
|
+
expect(translations.first.language).to eq('en-GB')
|
74
|
+
expect(translations.last.name).to eq('Parent 1 de')
|
75
|
+
end
|
70
76
|
end
|
71
77
|
|
72
78
|
it 'has subnodes' do
|
73
|
-
|
74
|
-
|
75
|
-
|
79
|
+
nodes = first_node.nodes
|
80
|
+
|
81
|
+
aggregate_failures do
|
82
|
+
expect(nodes).to be_kind_of(Enumerable)
|
83
|
+
expect(nodes).not_to be_empty
|
84
|
+
expect(nodes.length).to eq(1)
|
85
|
+
end
|
76
86
|
end
|
77
87
|
|
78
88
|
it 'first node - first node name' do
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'Using inheritance to share elements and attributes' do
|
5
|
+
RSpec.describe 'Using inheritance to share elements and attributes', type: :feature do
|
6
6
|
class Genetics
|
7
7
|
include HappyMapper
|
8
8
|
content :dna, String
|
@@ -28,7 +28,7 @@ describe 'Using inheritance to share elements and attributes' do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
describe 'Overwrite' do
|
31
|
-
let(:
|
31
|
+
let(:overwrite) do
|
32
32
|
xml =
|
33
33
|
'<overwrite love="love" naivety="trusting">' \
|
34
34
|
'<genetics>1001</genetics><immunities>Chicken Pox</immunities>' \
|
@@ -37,22 +37,24 @@ describe 'Using inheritance to share elements and attributes' do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'overrides the parent elements and attributes' do
|
40
|
-
|
41
|
-
|
40
|
+
aggregate_failures do
|
41
|
+
expect(Overwrite.attributes.count).to eq Parent.attributes.count
|
42
|
+
expect(Overwrite.elements.count).to eq Parent.elements.count
|
43
|
+
end
|
42
44
|
end
|
43
45
|
|
44
46
|
context 'when parsing xml' do
|
45
47
|
it 'parses the new overwritten attribut' do
|
46
|
-
expect(
|
48
|
+
expect(overwrite.love).to be == 'love'
|
47
49
|
end
|
48
50
|
|
49
51
|
it 'parses the new overwritten element' do
|
50
|
-
expect(
|
52
|
+
expect(overwrite.genetics).to be == 1001
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
56
|
context 'when saving to xml' do
|
55
|
-
|
57
|
+
let(:xml) do
|
56
58
|
overwrite = Overwrite.new
|
57
59
|
overwrite.genetics = 1
|
58
60
|
overwrite.love = 'love'
|
@@ -60,17 +62,17 @@ describe 'Using inheritance to share elements and attributes' do
|
|
60
62
|
end
|
61
63
|
|
62
64
|
it 'has only 1 genetics element' do
|
63
|
-
expect(
|
65
|
+
expect(xml.xpath('//genetics').count).to be == 1
|
64
66
|
end
|
65
67
|
|
66
68
|
it 'has only 1 love attribute' do
|
67
|
-
expect(
|
69
|
+
expect(xml.xpath('@love').text).to be == 'love'
|
68
70
|
end
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
74
|
describe 'Child', 'a subclass of the Parent' do
|
73
|
-
let(:
|
75
|
+
let(:child) do
|
74
76
|
xml =
|
75
77
|
'<child love="99" naivety="trusting">' \
|
76
78
|
'<genetics>ABBA</genetics><immunities>Chicken Pox</immunities>' \
|
@@ -80,15 +82,17 @@ describe 'Using inheritance to share elements and attributes' do
|
|
80
82
|
|
81
83
|
context 'when parsing xml' do
|
82
84
|
it 'is possible to deserialize XML into a Child class instance' do
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
aggregate_failures do
|
86
|
+
expect(child.love).to eq 99
|
87
|
+
expect(child.genetics.dna).to eq 'ABBA'
|
88
|
+
expect(child.naivety).to eq 'trusting'
|
89
|
+
expect(child.immunities.size).to eq(1)
|
90
|
+
end
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
90
94
|
context 'when saving to xml' do
|
91
|
-
let(:
|
95
|
+
let(:xml) do
|
92
96
|
child = Child.new
|
93
97
|
child.love = 100
|
94
98
|
child.naivety = 'Bright Eyed'
|
@@ -100,13 +104,17 @@ describe 'Using inheritance to share elements and attributes' do
|
|
100
104
|
end
|
101
105
|
|
102
106
|
it 'saves both the Child and Parent attributes' do
|
103
|
-
|
104
|
-
|
107
|
+
aggregate_failures do
|
108
|
+
expect(xml.xpath('@naivety').text).to eq 'Bright Eyed'
|
109
|
+
expect(xml.xpath('@love').text).to eq '100'
|
110
|
+
end
|
105
111
|
end
|
106
112
|
|
107
113
|
it 'saves both the Child and Parent elements' do
|
108
|
-
|
109
|
-
|
114
|
+
aggregate_failures do
|
115
|
+
expect(xml.xpath('genetics').text).to eq 'GATTACA'
|
116
|
+
expect(xml.xpath('immunities').size).to eq(3)
|
117
|
+
end
|
110
118
|
end
|
111
119
|
end
|
112
120
|
end
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'Updating existing objects with .parse and #parse' do
|
6
|
-
let(:
|
5
|
+
RSpec.describe 'Updating existing objects with .parse and #parse', type: :feature do
|
6
|
+
let(:root) { ParseInstanceSpec::Root.parse(parse_instance_initial_xml) }
|
7
7
|
|
8
8
|
let(:parse_instance_initial_xml) do
|
9
9
|
%(<root attr1="initial">
|
@@ -83,28 +83,34 @@ describe 'Updating existing objects with .parse and #parse' do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it 'initial values are correct' do
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
aggregate_failures do
|
87
|
+
expect(root.attr1).to eq('initial')
|
88
|
+
item_is_correctly_defined(root.items[0])
|
89
|
+
item_is_correctly_defined(root.items[1])
|
90
|
+
end
|
89
91
|
end
|
90
92
|
|
91
93
|
describe '.parse', 'specifying an existing object to update' do
|
92
94
|
it 'all fields are correct' do
|
93
|
-
ParseInstanceSpec::Root.parse(parse_instance_updated_xml, update:
|
94
|
-
expect(subject.attr1).to eq 'updated'
|
95
|
+
ParseInstanceSpec::Root.parse(parse_instance_updated_xml, update: root)
|
95
96
|
|
96
|
-
|
97
|
-
|
97
|
+
aggregate_failures do
|
98
|
+
expect(root.attr1).to eq 'updated'
|
99
|
+
item_is_correctly_defined(root.items[0], 'updated')
|
100
|
+
item_is_correctly_defined(root.items[1], 'updated')
|
101
|
+
end
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
101
105
|
describe '#parse' do
|
102
106
|
it 'all fields are correct' do
|
103
|
-
|
104
|
-
expect(subject.attr1).to eq 'updated'
|
107
|
+
root.parse(parse_instance_updated_xml)
|
105
108
|
|
106
|
-
|
107
|
-
|
109
|
+
aggregate_failures do
|
110
|
+
expect(root.attr1).to eq 'updated'
|
111
|
+
item_is_correctly_defined(root.items[0], 'updated')
|
112
|
+
item_is_correctly_defined(root.items[1], 'updated')
|
113
|
+
end
|
108
114
|
end
|
109
115
|
end
|
110
116
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe 'Saving #to_xml' do
|
5
|
+
RSpec.describe 'Saving #to_xml', type: :feature do
|
6
6
|
module ToXML
|
7
7
|
class Address
|
8
8
|
include HappyMapper
|
@@ -102,7 +102,7 @@ describe 'Saving #to_xml' do
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
-
let(:
|
105
|
+
let(:xml) do
|
106
106
|
country = ToXML::Country.new(name: 'USA', code: 'us', empty_code: nil,
|
107
107
|
description: ToXML::Country::Description.new('A lovely country'))
|
108
108
|
|
@@ -123,46 +123,46 @@ describe 'Saving #to_xml' do
|
|
123
123
|
it 'saves elements' do
|
124
124
|
elements = { 'street' => 'Mockingbird Lane', 'postcode' => '98103', 'city' => 'Seattle' }
|
125
125
|
elements.each_pair do |property, value|
|
126
|
-
expect(
|
126
|
+
expect(xml.xpath(property.to_s).text).to eq value
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
130
|
it 'saves attributes' do
|
131
|
-
expect(
|
131
|
+
expect(xml.xpath('@location').text).to eq 'Home-live'
|
132
132
|
end
|
133
133
|
|
134
134
|
it 'saves attributes that are Boolean and have a value of false' do
|
135
|
-
expect(
|
135
|
+
expect(xml.xpath('@occupied').text).to eq 'false'
|
136
136
|
end
|
137
137
|
|
138
138
|
context "when an element has a 'read_only' parameter" do
|
139
139
|
it 'does not save elements' do
|
140
|
-
expect(
|
140
|
+
expect(xml.xpath('temporary')).to be_empty
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
144
|
context "when an attribute has a 'read_only' parameter" do
|
145
145
|
it 'does not save attributes' do
|
146
|
-
expect(
|
146
|
+
expect(xml.xpath('@modified')).to be_empty
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
150
|
context "when an element has a 'state_when_nil' parameter" do
|
151
151
|
it 'saves an empty element' do
|
152
|
-
expect(
|
152
|
+
expect(xml.xpath('description').text).to eq ''
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
156
|
context "when an element has a 'on_save' parameter" do
|
157
157
|
context 'with a symbol which represents a function' do
|
158
158
|
it 'saves the element with the result of the function' do
|
159
|
-
expect(
|
159
|
+
expect(xml.xpath('housenumber').text).to eq '[1313]'
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
163
|
context 'with a lambda' do
|
164
164
|
it 'saves the result of the lambda' do
|
165
|
-
expect(
|
165
|
+
expect(xml.xpath('date_created').text).to eq '15:00:00 01/01/11'
|
166
166
|
end
|
167
167
|
end
|
168
168
|
end
|
@@ -170,10 +170,13 @@ describe 'Saving #to_xml' do
|
|
170
170
|
context "when a has_many has a 'on_save' parameter" do
|
171
171
|
context 'with a lambda' do
|
172
172
|
it 'saves the results' do
|
173
|
-
dates_updated =
|
174
|
-
|
175
|
-
|
176
|
-
|
173
|
+
dates_updated = xml.xpath('dates_updated')
|
174
|
+
|
175
|
+
aggregate_failures do
|
176
|
+
expect(dates_updated.length).to eq 2
|
177
|
+
expect(dates_updated.first.text).to eq '16:01:00 01/01/11'
|
178
|
+
expect(dates_updated.last.text).to eq '11:30:01 01/02/11'
|
179
|
+
end
|
177
180
|
end
|
178
181
|
end
|
179
182
|
end
|
@@ -181,22 +184,22 @@ describe 'Saving #to_xml' do
|
|
181
184
|
context "when an attribute has a 'on_save' parameter" do
|
182
185
|
context 'with a symbol which represents a function' do
|
183
186
|
it 'saves the result' do
|
184
|
-
expect(
|
187
|
+
expect(xml.xpath('@location').text).to eq 'Home-live'
|
185
188
|
end
|
186
189
|
end
|
187
190
|
end
|
188
191
|
|
189
192
|
context 'when an element type is a HappyMapper subclass' do
|
190
193
|
it 'saves attributes' do
|
191
|
-
expect(
|
194
|
+
expect(xml.xpath('country/@countryCode').text).to eq 'us'
|
192
195
|
end
|
193
196
|
|
194
197
|
it 'saves elements with a specified tag' do
|
195
|
-
expect(
|
198
|
+
expect(xml.xpath('country/countryName').text).to eq 'USA'
|
196
199
|
end
|
197
200
|
|
198
201
|
it 'saves elements with content' do
|
199
|
-
expect(
|
202
|
+
expect(xml.xpath('country/description').text).to eq 'A lovely country'
|
200
203
|
end
|
201
204
|
end
|
202
205
|
end
|