nokogiri-happymapper 0.5.6 → 0.5.7
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 +15 -0
- data/CHANGELOG.md +5 -1
- data/README.md +74 -53
- data/lib/happymapper/anonymous_mapper.rb +114 -0
- data/lib/happymapper/attribute.rb +20 -2
- data/lib/happymapper/element.rb +52 -2
- data/lib/happymapper/item.rb +89 -182
- data/lib/happymapper/supported_types.rb +140 -0
- data/lib/happymapper/text_node.rb +6 -1
- data/lib/happymapper/version.rb +3 -0
- data/lib/happymapper.rb +42 -22
- data/spec/attribute_default_value_spec.rb +50 -0
- data/spec/fixtures/default_namespace_combi.xml +2 -1
- data/spec/happymapper/attribute_spec.rb +12 -0
- data/spec/happymapper/element_spec.rb +9 -0
- data/spec/{happymapper_item_spec.rb → happymapper/item_spec.rb} +5 -5
- data/spec/happymapper/text_node_spec.rb +9 -0
- data/spec/happymapper_parse_spec.rb +87 -0
- data/spec/happymapper_spec.rb +9 -3
- data/spec/ignay_spec.rb +22 -22
- data/spec/inheritance_spec.rb +61 -0
- data/spec/parse_with_object_to_update_spec.rb +111 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/to_xml_spec.rb +200 -0
- data/spec/to_xml_with_namespaces_spec.rb +196 -0
- data/spec/wilcard_tag_name_spec.rb +96 -0
- data/spec/wrap_spec.rb +82 -0
- data/spec/xpath_spec.rb +60 -59
- metadata +34 -33
- data/TODO +0 -0
- data/spec/happymapper_attribute_spec.rb +0 -21
- data/spec/happymapper_element_spec.rb +0 -21
- data/spec/happymapper_generic_base_spec.rb +0 -92
- data/spec/happymapper_text_node_spec.rb +0 -21
- data/spec/happymapper_to_xml_namespaces_spec.rb +0 -196
- data/spec/happymapper_to_xml_spec.rb +0 -203
- data/spec/happymapper_wrap_spec.rb +0 -69
- data/spec/parse_instance_spec.rb +0 -129
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
module Foo
|
4
4
|
class Bar; end
|
@@ -33,18 +33,18 @@ describe HappyMapper::Item do
|
|
33
33
|
item = HappyMapper::Item.new(:foo, String)
|
34
34
|
item.constant.should == String
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
it "should convert string type to constant" do
|
38
38
|
item = HappyMapper::Item.new(:foo, 'String')
|
39
39
|
item.constant.should == String
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
it "should convert string with :: to constant" do
|
43
43
|
item = HappyMapper::Item.new(:foo, 'Foo::Bar')
|
44
44
|
item.constant.should == Foo::Bar
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
describe "#method_name" do
|
49
49
|
it "should convert dashes to underscores" do
|
50
50
|
item = HappyMapper::Item.new(:'foo-bar', String, :tag => 'foobar')
|
@@ -108,7 +108,7 @@ describe HappyMapper::Item do
|
|
108
108
|
end
|
109
109
|
|
110
110
|
it "should work with Boolean" do
|
111
|
-
item = HappyMapper::Item.new(:foo, Boolean)
|
111
|
+
item = HappyMapper::Item.new(:foo, HappyMapper::Boolean)
|
112
112
|
item.typecast('false').should == false
|
113
113
|
end
|
114
114
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe HappyMapper do
|
4
|
+
|
5
|
+
context ".parse" do
|
6
|
+
|
7
|
+
context "on a single root node" do
|
8
|
+
|
9
|
+
subject { described_class.parse fixture_file('address.xml') }
|
10
|
+
|
11
|
+
it "should parse child elements" do
|
12
|
+
subject.street.should == "Milchstrasse"
|
13
|
+
subject.housenumber.should == "23"
|
14
|
+
subject.postcode.should == "26131"
|
15
|
+
subject.city.should == "Oldenburg"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should not create a content entry when the xml contents no text content" do
|
19
|
+
subject.should_not respond_to :content
|
20
|
+
end
|
21
|
+
|
22
|
+
context "child elements with attributes" do
|
23
|
+
|
24
|
+
it "should parse the attributes" do
|
25
|
+
subject.country.code.should == "de"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should parse the content" do
|
29
|
+
subject.country.content.should == "Germany"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
context "element names with special characters" do
|
37
|
+
subject { described_class.parse fixture_file('ambigous_items.xml') }
|
38
|
+
|
39
|
+
it "should create accessor methods with similar names" do
|
40
|
+
subject.my_items.item.should be_kind_of Array
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "element names with camelCased elements and Capital Letters" do
|
45
|
+
|
46
|
+
subject { described_class.parse fixture_file('subclass_namespace.xml') }
|
47
|
+
|
48
|
+
it "should parse the elements an values correctly" do
|
49
|
+
subject.title.should == "article title"
|
50
|
+
subject.photo.publish_options.author.should == "Stephanie"
|
51
|
+
subject.gallery.photo.title.should == "photo title"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "several elements nested deep" do
|
56
|
+
subject { described_class.parse fixture_file('ambigous_items.xml') }
|
57
|
+
|
58
|
+
it "should parse the entire relationship" do
|
59
|
+
subject.my_items.item.first.item.name.should == "My first internal item"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "xml that contains multiple entries" do
|
64
|
+
|
65
|
+
subject { described_class.parse fixture_file('multiple_primitives.xml') }
|
66
|
+
|
67
|
+
it "should parse the elements as it would a 'has_many'" do
|
68
|
+
|
69
|
+
subject.name.should == "value"
|
70
|
+
subject.image.should == [ "image1", "image2" ]
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "xml with multiple namespaces" do
|
77
|
+
|
78
|
+
subject { described_class.parse fixture_file('subclass_namespace.xml') }
|
79
|
+
|
80
|
+
it "should parse the elements an values correctly" do
|
81
|
+
subject.title.should == "article title"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
data/spec/happymapper_spec.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
require
|
2
|
-
require 'pp'
|
3
|
-
require 'uri'
|
1
|
+
require 'spec_helper'
|
4
2
|
|
5
3
|
module Analytics
|
6
4
|
class Property
|
@@ -282,6 +280,8 @@ end
|
|
282
280
|
class Status
|
283
281
|
include HappyMapper
|
284
282
|
|
283
|
+
register_namespace 'fake', "faka:namespace"
|
284
|
+
|
285
285
|
element :id, Integer
|
286
286
|
element :text, String
|
287
287
|
element :created_at, Time
|
@@ -553,12 +553,14 @@ class DefaultNamespaceCombi
|
|
553
553
|
|
554
554
|
register_namespace 'bk', "urn:loc.gov:books"
|
555
555
|
register_namespace 'isbn', "urn:ISBN:0-395-36341-6"
|
556
|
+
register_namespace 'p', "urn:loc.gov:people"
|
556
557
|
namespace 'bk'
|
557
558
|
|
558
559
|
tag 'book'
|
559
560
|
|
560
561
|
element :title, String, :namespace => 'bk', :tag => "title"
|
561
562
|
element :number, String, :namespace => 'isbn', :tag => "number"
|
563
|
+
element :author, String, :namespace => 'p', :tag => "author"
|
562
564
|
end
|
563
565
|
|
564
566
|
describe HappyMapper do
|
@@ -972,6 +974,10 @@ describe HappyMapper do
|
|
972
974
|
@book = DefaultNamespaceCombi.parse(file_contents, :single => true)
|
973
975
|
end
|
974
976
|
|
977
|
+
it "should parse author" do
|
978
|
+
@book.author.should == "Frank Gilbreth"
|
979
|
+
end
|
980
|
+
|
975
981
|
it "should parse title" do
|
976
982
|
@book.title.should == "Cheaper by the Dozen"
|
977
983
|
end
|
data/spec/ignay_spec.rb
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
3
|
class CatalogTree
|
4
4
|
include HappyMapper
|
5
|
-
|
5
|
+
|
6
6
|
tag 'CatalogTree'
|
7
7
|
register_namespace 'xmlns', 'urn:eventis:prodis:onlineapi:1.0'
|
8
8
|
register_namespace 'xsi', 'http://www.w3.org/2001/XMLSchema-instance'
|
9
9
|
register_namespace 'xsd', 'http://www.w3.org/2001/XMLSchema'
|
10
10
|
|
11
11
|
attribute :code, String
|
12
|
-
|
12
|
+
|
13
13
|
has_many :nodes, 'CatalogNode', :tag => 'Node', :xpath => '.'
|
14
|
-
|
14
|
+
|
15
15
|
end
|
16
16
|
|
17
17
|
|
18
18
|
class CatalogNode
|
19
19
|
include HappyMapper
|
20
|
-
|
20
|
+
|
21
21
|
tag 'Node'
|
22
|
-
|
22
|
+
|
23
23
|
attribute :back_office_id, String, :tag => 'vodBackOfficeId'
|
24
|
-
|
24
|
+
|
25
25
|
has_one :name, String, :tag => 'Name'
|
26
26
|
# other important fields
|
27
|
-
|
27
|
+
|
28
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
34
|
attribute :language, String, :tag => 'Language'
|
35
35
|
has_one :name, String, :tag => 'Name'
|
36
|
-
|
36
|
+
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
has_many :nodes, CatalogNode, :tag => 'Node', :xpath => 'child::*'
|
40
|
-
|
40
|
+
|
41
41
|
end
|
42
42
|
|
43
43
|
describe HappyMapper do
|
@@ -45,30 +45,30 @@ describe HappyMapper do
|
|
45
45
|
it "should not be nil" do
|
46
46
|
catalog_tree.should_not be_nil
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it "should have the attribute code" do
|
50
50
|
catalog_tree.code.should == "NLD"
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
it "should have many nodes" do
|
54
54
|
catalog_tree.nodes.should_not be_empty
|
55
55
|
catalog_tree.nodes.length.should == 2
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
context "first node" do
|
59
|
-
|
59
|
+
|
60
60
|
it "should have a name" do
|
61
61
|
first_node.name.should == "Parent 1"
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
it "should have translations" do
|
65
65
|
first_node.translations.length.should == 2
|
66
|
-
|
66
|
+
|
67
67
|
first_node.translations.first.language.should == "en-GB"
|
68
|
-
|
68
|
+
|
69
69
|
first_node.translations.last.name.should == "Parent 1 de"
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
it "should have subnodes" do
|
73
73
|
first_node.nodes.should be_kind_of(Enumerable)
|
74
74
|
first_node.nodes.should_not be_empty
|
@@ -82,7 +82,7 @@ describe HappyMapper do
|
|
82
82
|
def first_node
|
83
83
|
@first_node = catalog_tree.nodes.first
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
end
|
87
87
|
|
88
88
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Using inheritance to share elements and attributes" do
|
4
|
+
|
5
|
+
class Genetics
|
6
|
+
include HappyMapper
|
7
|
+
content :dna, String
|
8
|
+
end
|
9
|
+
|
10
|
+
class Parent
|
11
|
+
include HappyMapper
|
12
|
+
attribute :love, Integer
|
13
|
+
element :genetics, Genetics
|
14
|
+
end
|
15
|
+
|
16
|
+
class Child < Parent
|
17
|
+
include HappyMapper
|
18
|
+
attribute :naivety, String
|
19
|
+
has_many :immunities, String
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "Child", "a subclass of the Parent" do
|
23
|
+
let(:subject) do
|
24
|
+
xml = '<child love="99" naivety="trusting"><genetics>ABBA</genetics><immunities>Chicken Pox</immunities></child>'
|
25
|
+
Child.parse(xml)
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when parsing xml" do
|
29
|
+
it 'should be possible to deserialize XML into a Child class instance' do
|
30
|
+
expect(subject.love).to eq 99
|
31
|
+
expect(subject.genetics.dna).to eq "ABBA"
|
32
|
+
expect(subject.naivety).to eq "trusting"
|
33
|
+
expect(subject.immunities).to have(1).item
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when saving to xml" do
|
38
|
+
let(:subject) do
|
39
|
+
child = Child.new
|
40
|
+
child.love = 100
|
41
|
+
child.naivety = 'Bright Eyed'
|
42
|
+
child.immunities = [ "Small Pox", "Chicken Pox", "Mumps" ]
|
43
|
+
genetics = Genetics.new
|
44
|
+
genetics.dna = "GATTACA"
|
45
|
+
child.genetics = genetics
|
46
|
+
Nokogiri::XML(child.to_xml).root
|
47
|
+
end
|
48
|
+
|
49
|
+
it "saves both the Child and Parent attributes" do
|
50
|
+
expect(subject.xpath("@naivety").text).to eq "Bright Eyed"
|
51
|
+
expect(subject.xpath("@love").text).to eq "100"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "saves both the Child and Parent elements" do
|
55
|
+
expect(subject.xpath("genetics").text).to eq "GATTACA"
|
56
|
+
expect(subject.xpath("immunities")).to have(3).items
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Updating existing objects with .parse and #parse" do
|
4
|
+
|
5
|
+
let(:subject) { ParseInstanceSpec::Root.parse(parse_instance_initial_xml) }
|
6
|
+
|
7
|
+
let(:parse_instance_initial_xml) do
|
8
|
+
%{<root attr1="initial">
|
9
|
+
<item attr1="initial">
|
10
|
+
<description>initial</description>
|
11
|
+
<subitem attr1="initial">
|
12
|
+
<name>initial</name>
|
13
|
+
</subitem>
|
14
|
+
<subitem attr1="initial">
|
15
|
+
<name>initial</name>
|
16
|
+
</subitem>
|
17
|
+
</item>
|
18
|
+
<item attr1="initial">
|
19
|
+
<description>initial</description>
|
20
|
+
<subitem attr1="initial">
|
21
|
+
<name>initial</name>
|
22
|
+
</subitem>
|
23
|
+
<subitem attr1="initial">
|
24
|
+
<name>initial</name>
|
25
|
+
</subitem>
|
26
|
+
</item>
|
27
|
+
</root>}
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:parse_instance_updated_xml) do
|
31
|
+
%{<root attr1="updated">
|
32
|
+
<item attr1="updated">
|
33
|
+
<description>updated</description>
|
34
|
+
<subitem attr1="updated">
|
35
|
+
<name>updated</name>
|
36
|
+
</subitem>
|
37
|
+
<subitem attr1="updated">
|
38
|
+
<name>updated</name>
|
39
|
+
</subitem>
|
40
|
+
</item>
|
41
|
+
<item attr1="updated">
|
42
|
+
<description>updated</description>
|
43
|
+
<subitem attr1="updated">
|
44
|
+
<name>updated</name>
|
45
|
+
</subitem>
|
46
|
+
<subitem attr1="updated">
|
47
|
+
<name>updated</name>
|
48
|
+
</subitem>
|
49
|
+
</item>
|
50
|
+
</root>}
|
51
|
+
end
|
52
|
+
|
53
|
+
module ParseInstanceSpec
|
54
|
+
class SubItem
|
55
|
+
include HappyMapper
|
56
|
+
tag 'subitem'
|
57
|
+
attribute :attr1, String
|
58
|
+
element :name, String
|
59
|
+
end
|
60
|
+
class Item
|
61
|
+
include HappyMapper
|
62
|
+
tag 'item'
|
63
|
+
attribute :attr1, String
|
64
|
+
element :description, String
|
65
|
+
has_many :sub_items, SubItem
|
66
|
+
end
|
67
|
+
class Root
|
68
|
+
include HappyMapper
|
69
|
+
tag 'root'
|
70
|
+
attribute :attr1, String
|
71
|
+
has_many :items, Item
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def item_is_correctly_defined(item,value='initial')
|
76
|
+
expect(item.attr1).to eq value
|
77
|
+
expect(item.description).to eq value
|
78
|
+
expect(item.sub_items[0].attr1).to eq value
|
79
|
+
expect(item.sub_items[0].name).to eq value
|
80
|
+
expect(item.sub_items[1].attr1).to eq value
|
81
|
+
expect(item.sub_items[1].name).to eq value
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'initial values are correct' do
|
85
|
+
subject.attr1.should == 'initial'
|
86
|
+
item_is_correctly_defined( subject.items[0] )
|
87
|
+
item_is_correctly_defined( subject.items[1] )
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
describe ".parse", "specifying an existing object to update" do
|
92
|
+
it 'all fields are correct' do
|
93
|
+
ParseInstanceSpec::Root.parse(parse_instance_updated_xml, :update => subject)
|
94
|
+
expect(subject.attr1).to eq 'updated'
|
95
|
+
|
96
|
+
item_is_correctly_defined( subject.items[0], 'updated' )
|
97
|
+
item_is_correctly_defined( subject.items[1], 'updated' )
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "#parse" do
|
102
|
+
it "all fields are correct" do
|
103
|
+
subject.parse(parse_instance_updated_xml)
|
104
|
+
expect(subject.attr1).to eq 'updated'
|
105
|
+
|
106
|
+
item_is_correctly_defined( subject.items[0], 'updated' )
|
107
|
+
item_is_correctly_defined( subject.items[1], 'updated' )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/to_xml_spec.rb
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Saving #to_xml" do
|
4
|
+
|
5
|
+
module ToXML
|
6
|
+
class Address
|
7
|
+
include HappyMapper
|
8
|
+
|
9
|
+
tag 'address'
|
10
|
+
|
11
|
+
attribute :location, String, :on_save => :when_saving_location
|
12
|
+
|
13
|
+
element :street, String
|
14
|
+
element :postcode, String
|
15
|
+
element :city, String
|
16
|
+
|
17
|
+
element :housenumber, String
|
18
|
+
|
19
|
+
attribute :modified, Boolean, :read_only => true
|
20
|
+
element :temporary, Boolean, :read_only => true
|
21
|
+
#
|
22
|
+
# to_xml will default to the attr_accessor method and not the attribute,
|
23
|
+
# allowing for that to be overwritten
|
24
|
+
#
|
25
|
+
def housenumber
|
26
|
+
"[#{@housenumber}]"
|
27
|
+
end
|
28
|
+
|
29
|
+
def when_saving_location(loc)
|
30
|
+
loc + "-live"
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Write a empty element even if this is not specified
|
35
|
+
#
|
36
|
+
element :description, String, :state_when_nil => true
|
37
|
+
|
38
|
+
#
|
39
|
+
# Perform the on_save operation when saving
|
40
|
+
#
|
41
|
+
has_one :date_created, Time, :on_save => lambda {|time| DateTime.parse(time).strftime("%T %D") if time }
|
42
|
+
|
43
|
+
|
44
|
+
#
|
45
|
+
# Execute the method with the same name
|
46
|
+
|
47
|
+
#
|
48
|
+
# Write multiple elements and call on_save when saving
|
49
|
+
#
|
50
|
+
has_many :dates_updated, Time, :on_save => lambda {|times|
|
51
|
+
times.compact.map {|time| DateTime.parse(time).strftime("%T %D") } if times }
|
52
|
+
|
53
|
+
#
|
54
|
+
# Class composition
|
55
|
+
#
|
56
|
+
element :country, 'Country', :tag => 'country'
|
57
|
+
|
58
|
+
attribute :occupied, Boolean
|
59
|
+
|
60
|
+
def initialize(parameters)
|
61
|
+
parameters.each_pair do |property,value|
|
62
|
+
send("#{property}=",value) if respond_to?("#{property}=")
|
63
|
+
end
|
64
|
+
@modified = @temporary = true
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# Country is composed above the in Address class. Here is a demonstration
|
71
|
+
# of how to_xml will handle class composition as well as utilizing the tag
|
72
|
+
# value.
|
73
|
+
#
|
74
|
+
class Country
|
75
|
+
include HappyMapper
|
76
|
+
|
77
|
+
attribute :code, String, :tag => 'countryCode'
|
78
|
+
has_one :name, String, :tag => 'countryName'
|
79
|
+
has_one :description, 'Description', :tag => 'description'
|
80
|
+
|
81
|
+
#
|
82
|
+
# This inner-class here is to demonstrate saving a text node
|
83
|
+
# and optional attributes
|
84
|
+
#
|
85
|
+
class Description
|
86
|
+
include HappyMapper
|
87
|
+
content :description, String
|
88
|
+
attribute :category, String, :tag => 'category'
|
89
|
+
attribute :rating, String, :tag => 'rating', :state_when_nil => true
|
90
|
+
|
91
|
+
def initialize(desc)
|
92
|
+
@description = desc
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def initialize(parameters)
|
97
|
+
parameters.each_pair do |property,value|
|
98
|
+
send("#{property}=",value) if respond_to?("#{property}=")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
let(:subject) do
|
106
|
+
address = ToXML::Address.new 'street' => 'Mockingbird Lane',
|
107
|
+
'location' => 'Home',
|
108
|
+
'housenumber' => '1313',
|
109
|
+
'postcode' => '98103',
|
110
|
+
'city' => 'Seattle',
|
111
|
+
'country' => ToXML::Country.new(:name => 'USA', :code => 'us', :empty_code => nil,
|
112
|
+
:description => ToXML::Country::Description.new("A lovely country") ),
|
113
|
+
'date_created' => '2011-01-01 15:00:00',
|
114
|
+
'occupied' => false
|
115
|
+
|
116
|
+
address.dates_updated = ["2011-01-01 16:01:00","2011-01-02 11:30:01"]
|
117
|
+
|
118
|
+
Nokogiri::XML(address.to_xml).root
|
119
|
+
end
|
120
|
+
|
121
|
+
it "saves elements" do
|
122
|
+
elements = { 'street' => 'Mockingbird Lane', 'postcode' => '98103', 'city' => 'Seattle' }
|
123
|
+
elements.each_pair do |property,value|
|
124
|
+
expect(subject.xpath("#{property}").text).to eq value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "saves attributes" do
|
129
|
+
expect(subject.xpath('@location').text).to eq "Home-live"
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'saves attributes that are Boolean and have a value of false' do
|
133
|
+
expect(subject.xpath('@occupied').text).to eq "false"
|
134
|
+
end
|
135
|
+
|
136
|
+
context "when an element has a 'read_only' parameter" do
|
137
|
+
it "does not save elements" do
|
138
|
+
expect(subject.xpath('temporary')).to be_empty
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "when an attribute has a 'read_only' parameter" do
|
143
|
+
it "does not save attributes" do
|
144
|
+
expect(subject.xpath("@modified")).to be_empty
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context "when an element has a 'state_when_nil' parameter" do
|
149
|
+
it "saves an empty element" do
|
150
|
+
expect(subject.xpath('description').text).to eq ""
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when an element has a 'on_save' parameter" do
|
155
|
+
context "with a symbol which represents a function" do
|
156
|
+
it "saves the element with the result of the function" do
|
157
|
+
expect(subject.xpath("housenumber").text).to eq "[1313]"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with a lambda" do
|
162
|
+
it "saves the result of the lambda" do
|
163
|
+
expect(subject.xpath('date_created').text).to eq "15:00:00 01/01/11"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "when a has_many has a 'on_save' parameter" do
|
169
|
+
context "with a lambda" do
|
170
|
+
it "saves the results" do
|
171
|
+
dates_updated = subject.xpath('dates_updated')
|
172
|
+
expect(dates_updated.length).to eq 2
|
173
|
+
expect(dates_updated.first.text).to eq "16:01:00 01/01/11"
|
174
|
+
expect(dates_updated.last.text).to eq "11:30:01 01/02/11"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "when an attribute has a 'on_save' parameter" do
|
180
|
+
context "with a symbol which represents a function" do
|
181
|
+
it "saves the result" do
|
182
|
+
expect(subject.xpath('@location').text).to eq "Home-live"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "when an element type is a HappyMapper subclass" do
|
188
|
+
it "saves attributes" do
|
189
|
+
expect(subject.xpath('country/@countryCode').text).to eq "us"
|
190
|
+
end
|
191
|
+
|
192
|
+
it "saves elements" do
|
193
|
+
expect(subject.xpath('country/countryName').text).to eq "USA"
|
194
|
+
end
|
195
|
+
|
196
|
+
it "saves elements" do
|
197
|
+
expect(subject.xpath('country/description').text).to eq "A lovely country"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|