nokogiri-happymapper 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|