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