nokogiri-happymapper 0.6.0 → 0.7.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +26 -1
- data/README.md +204 -117
- data/lib/happymapper.rb +318 -343
- data/lib/happymapper/anonymous_mapper.rb +27 -29
- data/lib/happymapper/attribute.rb +7 -5
- data/lib/happymapper/element.rb +19 -24
- data/lib/happymapper/item.rb +18 -20
- data/lib/happymapper/supported_types.rb +20 -19
- data/lib/happymapper/text_node.rb +4 -3
- data/lib/happymapper/version.rb +3 -1
- data/spec/attribute_default_value_spec.rb +14 -15
- data/spec/attributes_spec.rb +14 -15
- data/spec/happymapper/attribute_spec.rb +4 -4
- data/spec/happymapper/element_spec.rb +3 -1
- data/spec/happymapper/item_spec.rb +49 -41
- data/spec/happymapper/text_node_spec.rb +3 -1
- data/spec/happymapper_parse_spec.rb +62 -44
- data/spec/happymapper_spec.rb +270 -263
- data/spec/has_many_empty_array_spec.rb +8 -7
- data/spec/ignay_spec.rb +27 -31
- data/spec/inheritance_spec.rb +30 -24
- data/spec/mixed_namespaces_spec.rb +14 -15
- data/spec/parse_with_object_to_update_spec.rb +37 -38
- data/spec/spec_helper.rb +18 -0
- data/spec/to_xml_spec.rb +64 -63
- data/spec/to_xml_with_namespaces_spec.rb +66 -64
- data/spec/wilcard_tag_name_spec.rb +25 -21
- data/spec/wrap_spec.rb +11 -11
- data/spec/xpath_spec.rb +33 -32
- metadata +33 -5
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
2
4
|
|
3
5
|
module Sheep
|
4
6
|
class Item
|
@@ -16,28 +18,27 @@ module Sheep
|
|
16
18
|
has_many :items, Item, tag: 'item'
|
17
19
|
|
18
20
|
has_many :items_with_a_different_name, Item, tag: 'item'
|
19
|
-
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
|
-
describe
|
24
|
+
describe 'emptyness' do
|
24
25
|
let(:xml) do
|
25
|
-
<<-
|
26
|
+
<<-XML
|
26
27
|
<navigator>
|
27
28
|
<items/>
|
28
29
|
</navigator>
|
29
|
-
|
30
|
+
XML
|
30
31
|
end
|
31
32
|
|
32
33
|
let(:navigator) do
|
33
34
|
Sheep::Navigator.parse(xml)
|
34
35
|
end
|
35
36
|
|
36
|
-
it
|
37
|
+
it 'returns an empty array' do
|
37
38
|
expect(navigator.items_with_a_different_name).to be_empty
|
38
39
|
end
|
39
40
|
|
40
|
-
it
|
41
|
+
it 'returns an empty array' do
|
41
42
|
expect(navigator.items).to be_empty
|
42
43
|
end
|
43
44
|
end
|
data/spec/ignay_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
|
3
5
|
class CatalogTree
|
@@ -10,86 +12,80 @@ class CatalogTree
|
|
10
12
|
|
11
13
|
attribute :code, String
|
12
14
|
|
13
|
-
has_many :nodes, 'CatalogNode', :
|
14
|
-
|
15
|
+
has_many :nodes, 'CatalogNode', tag: 'Node', xpath: '.'
|
15
16
|
end
|
16
17
|
|
17
|
-
|
18
18
|
class CatalogNode
|
19
19
|
include HappyMapper
|
20
20
|
|
21
21
|
tag 'Node'
|
22
22
|
|
23
|
-
attribute :back_office_id, String, :
|
23
|
+
attribute :back_office_id, String, tag: 'vodBackOfficeId'
|
24
24
|
|
25
|
-
has_one :name, String, :
|
25
|
+
has_one :name, String, tag: 'Name'
|
26
26
|
# other important fields
|
27
27
|
|
28
|
-
has_many :translations, 'CatalogNode::Translations', :
|
28
|
+
has_many :translations, 'CatalogNode::Translations', tag: 'Translation', xpath: 'child::*'
|
29
29
|
|
30
30
|
class Translations
|
31
31
|
include HappyMapper
|
32
32
|
tag 'Translation'
|
33
33
|
|
34
|
-
attribute :language, String, :
|
35
|
-
has_one :name, String, :
|
36
|
-
|
34
|
+
attribute :language, String, tag: 'Language'
|
35
|
+
has_one :name, String, tag: 'Name'
|
37
36
|
end
|
38
37
|
|
39
|
-
has_many :nodes, CatalogNode, :
|
40
|
-
|
38
|
+
has_many :nodes, CatalogNode, tag: 'Node', xpath: 'child::*'
|
41
39
|
end
|
42
40
|
|
43
41
|
describe HappyMapper do
|
44
|
-
|
45
|
-
it "should not be nil" do
|
42
|
+
it 'should not be nil' do
|
46
43
|
expect(catalog_tree).not_to be_nil
|
47
44
|
end
|
48
45
|
|
49
|
-
it
|
50
|
-
expect(catalog_tree.code).to eq(
|
46
|
+
it 'should have the attribute code' do
|
47
|
+
expect(catalog_tree.code).to eq('NLD')
|
51
48
|
end
|
52
49
|
|
53
|
-
it
|
50
|
+
it 'should have many nodes' do
|
54
51
|
expect(catalog_tree.nodes).not_to be_empty
|
55
52
|
expect(catalog_tree.nodes.length).to eq(2)
|
56
53
|
end
|
57
54
|
|
58
|
-
context
|
59
|
-
|
60
|
-
|
61
|
-
expect(first_node.name).to eq("Parent 1")
|
55
|
+
context 'first node' do
|
56
|
+
it 'should have a name' do
|
57
|
+
expect(first_node.name).to eq('Parent 1')
|
62
58
|
end
|
63
59
|
|
64
|
-
it
|
60
|
+
it 'should have translations' do
|
65
61
|
expect(first_node.translations.length).to eq(2)
|
66
62
|
|
67
|
-
expect(first_node.translations.first.language).to eq(
|
63
|
+
expect(first_node.translations.first.language).to eq('en-GB')
|
68
64
|
|
69
|
-
expect(first_node.translations.last.name).to eq(
|
65
|
+
expect(first_node.translations.last.name).to eq('Parent 1 de')
|
70
66
|
end
|
71
67
|
|
72
|
-
it
|
68
|
+
it 'should have subnodes' do
|
73
69
|
expect(first_node.nodes).to be_kind_of(Enumerable)
|
74
70
|
expect(first_node.nodes).not_to be_empty
|
75
71
|
expect(first_node.nodes.length).to eq(1)
|
76
72
|
end
|
77
73
|
|
78
|
-
it
|
79
|
-
expect(first_node.nodes.first.name).to eq(
|
74
|
+
it 'first node - first node name' do
|
75
|
+
expect(first_node.nodes.first.name).to eq('First')
|
80
76
|
end
|
81
77
|
|
82
78
|
def first_node
|
83
79
|
@first_node = catalog_tree.nodes.first
|
84
80
|
end
|
85
|
-
|
86
81
|
end
|
87
82
|
|
88
|
-
|
89
|
-
|
83
|
+
def catalog_tree
|
84
|
+
@catalog_tree
|
85
|
+
end
|
90
86
|
|
91
87
|
before(:all) do
|
92
88
|
xml_reference = "#{File.dirname(__FILE__)}/fixtures/inagy.xml"
|
93
|
-
@catalog_tree = CatalogTree.parse(File.read(xml_reference), :
|
89
|
+
@catalog_tree = CatalogTree.parse(File.read(xml_reference), single: true)
|
94
90
|
end
|
95
|
-
end
|
91
|
+
end
|
data/spec/inheritance_spec.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
+
describe 'Using inheritance to share elements and attributes' do
|
5
6
|
class Genetics
|
6
7
|
include HappyMapper
|
7
8
|
content :dna, String
|
@@ -26,9 +27,12 @@ describe "Using inheritance to share elements and attributes" do
|
|
26
27
|
element :genetics, Integer
|
27
28
|
end
|
28
29
|
|
29
|
-
describe
|
30
|
+
describe 'Overwrite' do
|
30
31
|
let(:subject) do
|
31
|
-
xml =
|
32
|
+
xml =
|
33
|
+
'<overwrite love="love" naivety="trusting">' \
|
34
|
+
'<genetics>1001</genetics><immunities>Chicken Pox</immunities>' \
|
35
|
+
'</overwrite>'
|
32
36
|
Overwrite.parse(xml, single: true)
|
33
37
|
end
|
34
38
|
|
@@ -37,9 +41,9 @@ describe "Using inheritance to share elements and attributes" do
|
|
37
41
|
expect(Overwrite.elements.count).to be == Parent.elements.count
|
38
42
|
end
|
39
43
|
|
40
|
-
context
|
44
|
+
context 'when parsing xml' do
|
41
45
|
it 'parses the new overwritten attribut' do
|
42
|
-
expect(subject.love).to be ==
|
46
|
+
expect(subject.love).to be == 'love'
|
43
47
|
end
|
44
48
|
|
45
49
|
it 'parses the new overwritten element' do
|
@@ -47,11 +51,11 @@ describe "Using inheritance to share elements and attributes" do
|
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
|
-
context
|
54
|
+
context 'when saving to xml' do
|
51
55
|
subject do
|
52
56
|
overwrite = Overwrite.new
|
53
57
|
overwrite.genetics = 1
|
54
|
-
overwrite.love =
|
58
|
+
overwrite.love = 'love'
|
55
59
|
Nokogiri::XML(overwrite.to_xml).root
|
56
60
|
end
|
57
61
|
|
@@ -60,48 +64,50 @@ describe "Using inheritance to share elements and attributes" do
|
|
60
64
|
end
|
61
65
|
|
62
66
|
it 'has only 1 love attribute' do
|
63
|
-
expect(subject.xpath('@love').text).to be ==
|
67
|
+
expect(subject.xpath('@love').text).to be == 'love'
|
64
68
|
end
|
65
69
|
end
|
66
70
|
end
|
67
71
|
|
68
|
-
describe
|
72
|
+
describe 'Child', 'a subclass of the Parent' do
|
69
73
|
let(:subject) do
|
70
|
-
xml =
|
74
|
+
xml =
|
75
|
+
'<child love="99" naivety="trusting">' \
|
76
|
+
'<genetics>ABBA</genetics><immunities>Chicken Pox</immunities>' \
|
77
|
+
'</child>'
|
71
78
|
Child.parse(xml)
|
72
79
|
end
|
73
80
|
|
74
|
-
context
|
81
|
+
context 'when parsing xml' do
|
75
82
|
it 'should be possible to deserialize XML into a Child class instance' do
|
76
83
|
expect(subject.love).to eq 99
|
77
|
-
expect(subject.genetics.dna).to eq
|
78
|
-
expect(subject.naivety).to eq
|
84
|
+
expect(subject.genetics.dna).to eq 'ABBA'
|
85
|
+
expect(subject.naivety).to eq 'trusting'
|
79
86
|
expect(subject.immunities.size).to eq(1)
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
83
|
-
context
|
90
|
+
context 'when saving to xml' do
|
84
91
|
let(:subject) do
|
85
92
|
child = Child.new
|
86
93
|
child.love = 100
|
87
94
|
child.naivety = 'Bright Eyed'
|
88
|
-
child.immunities = [
|
95
|
+
child.immunities = ['Small Pox', 'Chicken Pox', 'Mumps']
|
89
96
|
genetics = Genetics.new
|
90
|
-
genetics.dna =
|
97
|
+
genetics.dna = 'GATTACA'
|
91
98
|
child.genetics = genetics
|
92
99
|
Nokogiri::XML(child.to_xml).root
|
93
100
|
end
|
94
101
|
|
95
|
-
it
|
96
|
-
expect(subject.xpath(
|
97
|
-
expect(subject.xpath(
|
102
|
+
it 'saves both the Child and Parent attributes' do
|
103
|
+
expect(subject.xpath('@naivety').text).to eq 'Bright Eyed'
|
104
|
+
expect(subject.xpath('@love').text).to eq '100'
|
98
105
|
end
|
99
106
|
|
100
|
-
it
|
101
|
-
expect(subject.xpath(
|
102
|
-
expect(subject.xpath(
|
107
|
+
it 'saves both the Child and Parent elements' do
|
108
|
+
expect(subject.xpath('genetics').text).to eq 'GATTACA'
|
109
|
+
expect(subject.xpath('immunities').size).to eq(3)
|
103
110
|
end
|
104
111
|
end
|
105
|
-
|
106
112
|
end
|
107
113
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
+
describe 'A document with mixed namespaces' do
|
5
6
|
#
|
6
7
|
# Note that the parent element of the xml has the namespacing. The elements
|
7
8
|
# contained within the xml do not share the parent element namespace so a
|
@@ -9,14 +10,14 @@ describe "A document with mixed namespaces" do
|
|
9
10
|
# these child elements.
|
10
11
|
#
|
11
12
|
let(:xml_document) do
|
12
|
-
%
|
13
|
+
%(<prefix:address location='home' xmlns:prefix="http://www.unicornland.com/prefix"
|
13
14
|
xmlns:different="http://www.trollcountry.com/different">
|
14
15
|
<street>Milchstrasse</street>
|
15
16
|
<street>Another Street</street>
|
16
17
|
<housenumber>23</housenumber>
|
17
18
|
<different:postcode>26131</different:postcode>
|
18
19
|
<city>Oldenburg</city>
|
19
|
-
</prefix:address>
|
20
|
+
</prefix:address>)
|
20
21
|
end
|
21
22
|
|
22
23
|
module MixedNamespaces
|
@@ -41,21 +42,19 @@ describe "A document with mixed namespaces" do
|
|
41
42
|
MixedNamespaces::Address.parse(xml_document, single: true)
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
expect(address.streets).to eq [ "Milchstrasse", "Another Street" ]
|
45
|
+
it 'has the correct streets' do
|
46
|
+
expect(address.streets).to eq ['Milchstrasse', 'Another Street']
|
47
47
|
end
|
48
48
|
|
49
|
-
it
|
50
|
-
expect(address.house_number).to eq
|
49
|
+
it 'house number' do
|
50
|
+
expect(address.house_number).to eq '23'
|
51
51
|
end
|
52
52
|
|
53
|
-
it
|
54
|
-
expect(address.postcode).to eq
|
53
|
+
it 'postcode' do
|
54
|
+
expect(address.postcode).to eq '26131'
|
55
55
|
end
|
56
56
|
|
57
|
-
it
|
58
|
-
expect(address.city).to eq
|
57
|
+
it 'city' do
|
58
|
+
expect(address.city).to eq 'Oldenburg'
|
59
59
|
end
|
60
|
-
|
61
|
-
end
|
60
|
+
end
|
@@ -1,34 +1,35 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'spec_helper'
|
4
4
|
|
5
|
+
describe 'Updating existing objects with .parse and #parse' do
|
5
6
|
let(:subject) { ParseInstanceSpec::Root.parse(parse_instance_initial_xml) }
|
6
7
|
|
7
8
|
let(:parse_instance_initial_xml) do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
9
|
+
%(<root attr1="initial">
|
10
|
+
<item attr1="initial">
|
11
|
+
<description>initial</description>
|
12
|
+
<subitem attr1="initial">
|
13
|
+
<name>initial</name>
|
14
|
+
</subitem>
|
15
|
+
<subitem attr1="initial">
|
16
|
+
<name>initial</name>
|
17
|
+
</subitem>
|
18
|
+
</item>
|
19
|
+
<item attr1="initial">
|
20
|
+
<description>initial</description>
|
21
|
+
<subitem attr1="initial">
|
22
|
+
<name>initial</name>
|
23
|
+
</subitem>
|
24
|
+
<subitem attr1="initial">
|
25
|
+
<name>initial</name>
|
26
|
+
</subitem>
|
27
|
+
</item>
|
28
|
+
</root>)
|
28
29
|
end
|
29
30
|
|
30
31
|
let(:parse_instance_updated_xml) do
|
31
|
-
%
|
32
|
+
%(<root attr1="updated">
|
32
33
|
<item attr1="updated">
|
33
34
|
<description>updated</description>
|
34
35
|
<subitem attr1="updated">
|
@@ -47,7 +48,7 @@ describe "Updating existing objects with .parse and #parse" do
|
|
47
48
|
<name>updated</name>
|
48
49
|
</subitem>
|
49
50
|
</item>
|
50
|
-
</root>
|
51
|
+
</root>)
|
51
52
|
end
|
52
53
|
|
53
54
|
module ParseInstanceSpec
|
@@ -72,7 +73,7 @@ describe "Updating existing objects with .parse and #parse" do
|
|
72
73
|
end
|
73
74
|
end
|
74
75
|
|
75
|
-
def item_is_correctly_defined(item,value='initial')
|
76
|
+
def item_is_correctly_defined(item, value = 'initial')
|
76
77
|
expect(item.attr1).to eq value
|
77
78
|
expect(item.description).to eq value
|
78
79
|
expect(item.sub_items[0].attr1).to eq value
|
@@ -83,29 +84,27 @@ describe "Updating existing objects with .parse and #parse" do
|
|
83
84
|
|
84
85
|
it 'initial values are correct' do
|
85
86
|
expect(subject.attr1).to eq('initial')
|
86
|
-
item_is_correctly_defined(
|
87
|
-
item_is_correctly_defined(
|
87
|
+
item_is_correctly_defined(subject.items[0])
|
88
|
+
item_is_correctly_defined(subject.items[1])
|
88
89
|
end
|
89
90
|
|
90
|
-
|
91
|
-
describe ".parse", "specifying an existing object to update" do
|
91
|
+
describe '.parse', 'specifying an existing object to update' do
|
92
92
|
it 'all fields are correct' do
|
93
|
-
ParseInstanceSpec::Root.parse(parse_instance_updated_xml, :
|
93
|
+
ParseInstanceSpec::Root.parse(parse_instance_updated_xml, update: subject)
|
94
94
|
expect(subject.attr1).to eq 'updated'
|
95
95
|
|
96
|
-
item_is_correctly_defined(
|
97
|
-
item_is_correctly_defined(
|
96
|
+
item_is_correctly_defined(subject.items[0], 'updated')
|
97
|
+
item_is_correctly_defined(subject.items[1], 'updated')
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
describe
|
102
|
-
it
|
101
|
+
describe '#parse' do
|
102
|
+
it 'all fields are correct' do
|
103
103
|
subject.parse(parse_instance_updated_xml)
|
104
104
|
expect(subject.attr1).to eq 'updated'
|
105
105
|
|
106
|
-
item_is_correctly_defined(
|
107
|
-
item_is_correctly_defined(
|
106
|
+
item_is_correctly_defined(subject.items[0], 'updated')
|
107
|
+
item_is_correctly_defined(subject.items[1], 'updated')
|
108
108
|
end
|
109
109
|
end
|
110
|
-
|
111
|
-
end
|
110
|
+
end
|