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.
Files changed (38) hide show
  1. checksums.yaml +15 -0
  2. data/CHANGELOG.md +5 -1
  3. data/README.md +74 -53
  4. data/lib/happymapper/anonymous_mapper.rb +114 -0
  5. data/lib/happymapper/attribute.rb +20 -2
  6. data/lib/happymapper/element.rb +52 -2
  7. data/lib/happymapper/item.rb +89 -182
  8. data/lib/happymapper/supported_types.rb +140 -0
  9. data/lib/happymapper/text_node.rb +6 -1
  10. data/lib/happymapper/version.rb +3 -0
  11. data/lib/happymapper.rb +42 -22
  12. data/spec/attribute_default_value_spec.rb +50 -0
  13. data/spec/fixtures/default_namespace_combi.xml +2 -1
  14. data/spec/happymapper/attribute_spec.rb +12 -0
  15. data/spec/happymapper/element_spec.rb +9 -0
  16. data/spec/{happymapper_item_spec.rb → happymapper/item_spec.rb} +5 -5
  17. data/spec/happymapper/text_node_spec.rb +9 -0
  18. data/spec/happymapper_parse_spec.rb +87 -0
  19. data/spec/happymapper_spec.rb +9 -3
  20. data/spec/ignay_spec.rb +22 -22
  21. data/spec/inheritance_spec.rb +61 -0
  22. data/spec/parse_with_object_to_update_spec.rb +111 -0
  23. data/spec/spec_helper.rb +1 -1
  24. data/spec/to_xml_spec.rb +200 -0
  25. data/spec/to_xml_with_namespaces_spec.rb +196 -0
  26. data/spec/wilcard_tag_name_spec.rb +96 -0
  27. data/spec/wrap_spec.rb +82 -0
  28. data/spec/xpath_spec.rb +60 -59
  29. metadata +34 -33
  30. data/TODO +0 -0
  31. data/spec/happymapper_attribute_spec.rb +0 -21
  32. data/spec/happymapper_element_spec.rb +0 -21
  33. data/spec/happymapper_generic_base_spec.rb +0 -92
  34. data/spec/happymapper_text_node_spec.rb +0 -21
  35. data/spec/happymapper_to_xml_namespaces_spec.rb +0 -196
  36. data/spec/happymapper_to_xml_spec.rb +0 -203
  37. data/spec/happymapper_wrap_spec.rb +0 -69
  38. data/spec/parse_instance_spec.rb +0 -129
@@ -1,21 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- describe HappyMapper::Attribute do
4
- describe "initialization" do
5
- before do
6
- @attr = HappyMapper::Attribute.new(:foo, String)
7
- end
8
-
9
- it 'should know that it is an attribute' do
10
- @attr.attribute?.should be_true
11
- end
12
-
13
- it 'should know that it is NOT an element' do
14
- @attr.element?.should be_false
15
- end
16
-
17
- it 'should know that it is NOT a text node' do
18
- @attr.text_node?.should be_false
19
- end
20
- end
21
- end
@@ -1,21 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- describe HappyMapper::Element do
4
- describe "initialization" do
5
- before do
6
- @attr = HappyMapper::Element.new(:foo, String)
7
- end
8
-
9
- it 'should know that it is an element' do
10
- @attr.element?.should be_true
11
- end
12
-
13
- it 'should know that it is NOT an attribute' do
14
- @attr.attribute?.should be_false
15
- end
16
-
17
- it 'should know that it is NOT a text node' do
18
- @attr.text_node?.should be_false
19
- end
20
- end
21
- end
@@ -1,92 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
-
4
- generic_class_xml = %{
5
- <root>
6
- <description>some description</description>
7
- <blarg name='blargname1' href='http://blarg.com'/>
8
- <blarg name='blargname2' href='http://blarg.com'/>
9
- <jello name='jelloname' href='http://jello.com'/>
10
- <subelement>
11
- <jello name='subjelloname' href='http://ohnojello.com' other='othertext'/>
12
- </subelement>
13
- </root>
14
- }
15
-
16
- module GenericBase
17
- class Base
18
- include HappyMapper
19
- tag '*'
20
- attribute :name, String
21
- attribute :href, String
22
- attribute :other, String
23
- end
24
- class Sub
25
- include HappyMapper
26
- tag 'subelement'
27
- has_one :jello, Base, :tag => 'jello'
28
- end
29
- class Root
30
- include HappyMapper
31
- tag 'root'
32
- element :description, String
33
- has_many :blargs, Base, :tag => 'blarg', :xpath => '.'
34
- has_many :jellos, Base, :tag => 'jello', :xpath => '.'
35
- has_many :subjellos, Base, :tag => 'jello', :xpath => 'subelement/.', :read_only => true
36
- has_one :sub_element, Sub
37
- end
38
- end
39
-
40
-
41
- describe HappyMapper do
42
- describe "can have generic classes using tag '*'" do
43
-
44
- before(:all) do
45
- @root = GenericBase::Root.parse(generic_class_xml)
46
- @xml = Nokogiri::XML(@root.to_xml)
47
- end
48
-
49
- it 'should map different elements to same class' do
50
- @root.blargs.should_not be_nil
51
- @root.jellos.should_not be_nil
52
- end
53
-
54
- it 'should filter on xpath appropriately' do
55
- @root.blargs.should have(2).items
56
- @root.jellos.should have(1).items
57
- @root.subjellos.should have(1).items
58
- end
59
-
60
- it 'should parse correct values onto generic class' do
61
- @root.blargs[0].name.should == 'blargname1'
62
- @root.blargs[0].href.should == 'http://blarg.com'
63
- @root.blargs[0].other.should be_nil
64
- @root.blargs[1].name.should == 'blargname2'
65
- @root.blargs[1].href.should == 'http://blarg.com'
66
- @root.blargs[1].other.should be_nil
67
- @root.jellos[0].name.should == 'jelloname'
68
- @root.jellos[0].href.should == 'http://jello.com'
69
- @root.jellos[0].other.should be_nil
70
- @root.subjellos[0].name.should == 'subjelloname'
71
- @root.subjellos[0].href.should == 'http://ohnojello.com'
72
- @root.subjellos[0].other.should == 'othertext'
73
- end
74
-
75
- it 'should #to_xml using parent element tag name' do
76
- @xml.xpath('/root/description').text.should == 'some description'
77
- @xml.xpath('/root/blarg[1]/@name').text.should == 'blargname1'
78
- @xml.xpath('/root/blarg[1]/@href').text.should == 'http://blarg.com'
79
- @xml.xpath('/root/blarg[1]/@other').text.should be_empty
80
- @xml.xpath('/root/blarg[2]/@name').text.should == 'blargname2'
81
- @xml.xpath('/root/blarg[2]/@href').text.should == 'http://blarg.com'
82
- @xml.xpath('/root/blarg[2]/@other').text.should be_empty
83
- @xml.xpath('/root/jello[1]/@name').text.should == 'jelloname'
84
- @xml.xpath('/root/jello[1]/@href').text.should == 'http://jello.com'
85
- @xml.xpath('/root/jello[1]/@other').text.should be_empty
86
- end
87
-
88
- it "should properly respect child HappyMapper tags if tag isn't provided on the element defintion" do
89
- @xml.xpath('root/subelement').should have(1).item
90
- end
91
- end
92
- end
@@ -1,21 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- describe HappyMapper::Attribute do
4
- describe "initialization" do
5
- before do
6
- @attr = HappyMapper::TextNode.new(:foo, String)
7
- end
8
-
9
- it 'should know that it is a text node' do
10
- @attr.text_node?.should be_true
11
- end
12
-
13
- it 'should know that it is NOT an element' do
14
- @attr.element?.should be_false
15
- end
16
-
17
- it 'should know that it is NOT an attribute' do
18
- @attr.attribute?.should be_false
19
- end
20
- end
21
- end
@@ -1,196 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- module ToXMLWithNamespaces
4
-
5
- #
6
- # Similar example as the to_xml but this time with namespacing
7
- #
8
- class Address
9
- include HappyMapper
10
-
11
- register_namespace 'address', 'http://www.company.com/address'
12
- register_namespace 'country', 'http://www.company.com/country'
13
-
14
- tag 'Address'
15
- namespace 'address'
16
-
17
- element :country, 'Country', :tag => 'country', :namespace => 'country'
18
-
19
- attribute :location, String, :on_save => :when_saving_location
20
-
21
- element :street, String
22
- element :postcode, String
23
- element :city, String
24
-
25
- element :housenumber, String
26
-
27
- #
28
- # to_xml will default to the attr_accessor method and not the attribute,
29
- # allowing for that to be overwritten
30
- #
31
- def housenumber
32
- "[#{@housenumber}]"
33
- end
34
-
35
- def when_saving_location(loc)
36
- loc + '-live'
37
- end
38
-
39
- #
40
- # Write a empty element even if this is not specified
41
- #
42
- element :description, String, :state_when_nil => true
43
-
44
- #
45
- # Perform the on_save operation when saving
46
- #
47
- has_one :date_created, Time, :on_save => lambda {|time| DateTime.parse(time).strftime("%T %D") if time }
48
-
49
- #
50
- # Write multiple elements and call on_save when saving
51
- #
52
- has_many :dates_updated, Time, :on_save => lambda {|times|
53
- times.compact.map {|time| DateTime.parse(time).strftime("%T %D") } if times }
54
-
55
- #
56
- # Class composition
57
- #
58
-
59
- def initialize(parameters)
60
- parameters.each_pair do |property,value|
61
- send("#{property}=",value) if respond_to?("#{property}=")
62
- end
63
- end
64
-
65
- end
66
-
67
- #
68
- # Country is composed above the in Address class. Here is a demonstration
69
- # of how to_xml will handle class composition as well as utilizing the tag
70
- # value.
71
- #
72
- class Country
73
- include HappyMapper
74
-
75
- register_namespace 'countryName', 'http://www.company.com/countryName'
76
-
77
- attribute :code, String, :tag => 'countryCode'
78
- has_one :name, String, :tag => 'countryName', :namespace => 'countryName'
79
-
80
- def initialize(parameters)
81
- parameters.each_pair do |property,value|
82
- send("#{property}=",value) if respond_to?("#{property}=")
83
- end
84
- end
85
-
86
- end
87
-
88
-
89
- #
90
- # This class is an example of a class that has a default namespace
91
- #xmlns="urn:eventis:prodis:onlineapi:1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
92
- #
93
- class Recipe
94
- include HappyMapper
95
-
96
- # this is the default namespace of the document
97
- register_namespace 'xmlns', 'urn:eventis:prodis:onlineapi:1.0'
98
- register_namespace 'xsi', "http://www.w3.org/2001/XMLSchema-instance"
99
- register_namespace 'xsd', "http://www.w3.org/2001/XMLSchema"
100
-
101
- has_many :ingredients, String
102
-
103
- def initialize(parameters)
104
- parameters.each_pair {|property,value| send("#{property}=",value) if respond_to?("#{property}=") }
105
- end
106
- end
107
-
108
- describe HappyMapper do
109
-
110
- context "#to_xml", "with namespaces" do
111
-
112
- before(:all) do
113
- address = Address.new('street' => 'Mockingbird Lane',
114
- 'location' => 'Home',
115
- 'housenumber' => '1313',
116
- 'postcode' => '98103',
117
- 'city' => 'Seattle',
118
- 'country' => Country.new(:name => 'USA', :code => 'us'),
119
- 'date_created' => '2011-01-01 15:00:00')
120
-
121
-
122
- address.dates_updated = ["2011-01-01 16:01:00","2011-01-02 11:30:01"]
123
-
124
- @address_xml = Nokogiri::XML(address.to_xml).root
125
- end
126
-
127
- it "should save elements" do
128
-
129
- { 'street' => 'Mockingbird Lane',
130
- 'postcode' => '98103',
131
- 'city' => 'Seattle' }.each_pair do |property,value|
132
-
133
- @address_xml.xpath("address:#{property}").text.should == value
134
-
135
- end
136
-
137
- end
138
-
139
- it "should save the element with the result of a function call and not the value of the instance variable" do
140
- @address_xml.xpath("address:housenumber").text.should == "[1313]"
141
- end
142
-
143
- it "should save attributes" do
144
- @address_xml.xpath('@location').text.should == "Home-live"
145
- end
146
-
147
- context "state_when_nil options" do
148
-
149
- it "should save an empty element" do
150
- @address_xml.xpath('address:description').text.should == ""
151
- end
152
-
153
- end
154
-
155
- context "on_save option" do
156
-
157
- it "should save the result of the lambda" do
158
- @address_xml.xpath('address:date_created').text.should == "15:00:00 01/01/11"
159
- end
160
-
161
- it "should save the result of a method" do
162
- @address_xml.xpath('@location').text.should == "Home-live"
163
- end
164
-
165
- end
166
-
167
- it "should save elements defined with the 'has_many' relationship" do
168
- dates_updated = @address_xml.xpath('address:dates_updated')
169
- dates_updated.length.should == 2
170
- dates_updated.first.text.should == "16:01:00 01/01/11"
171
- dates_updated.last.text.should == "11:30:01 01/02/11"
172
- end
173
-
174
- context "class types that also include HappyMapper mappings" do
175
-
176
- it "should save attributes" do
177
- @address_xml.xpath('country:country/@country:countryCode').text.should == "us"
178
- end
179
-
180
- it "should save elements" do
181
- @address_xml.xpath('country:country/countryName:countryName').text.should == "USA"
182
- end
183
-
184
- end
185
-
186
- end
187
-
188
- context "#to_xml", "with a default namespace" do
189
- it "should write the default namespace to xml without repeating xmlns" do
190
- recipe = Recipe.new(:ingredients => ['One Cup Flour', 'Two Scoops of Lovin'])
191
- recipe.to_xml.should =~ /xmlns=\"urn:eventis:prodis:onlineapi:1\.0\"/
192
- end
193
- end
194
- end
195
-
196
- end
@@ -1,203 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- module ToXML
4
-
5
- class Address
6
- include HappyMapper
7
-
8
- tag 'address'
9
-
10
- attribute :location, String, :on_save => :when_saving_location
11
-
12
- element :street, String
13
- element :postcode, String
14
- element :city, String
15
-
16
- element :housenumber, String
17
-
18
- attribute :modified, Boolean, :read_only => true
19
- element :temporary, Boolean, :read_only => true
20
- #
21
- # to_xml will default to the attr_accessor method and not the attribute,
22
- # allowing for that to be overwritten
23
- #
24
- def housenumber
25
- "[#{@housenumber}]"
26
- end
27
-
28
- def when_saving_location(loc)
29
- loc + "-live"
30
- end
31
-
32
- #
33
- # Write a empty element even if this is not specified
34
- #
35
- element :description, String, :state_when_nil => true
36
-
37
- #
38
- # Perform the on_save operation when saving
39
- #
40
- has_one :date_created, Time, :on_save => lambda {|time| DateTime.parse(time).strftime("%T %D") if time }
41
-
42
-
43
- #
44
- # Execute the method with the same name
45
-
46
- #
47
- # Write multiple elements and call on_save when saving
48
- #
49
- has_many :dates_updated, Time, :on_save => lambda {|times|
50
- times.compact.map {|time| DateTime.parse(time).strftime("%T %D") } if times }
51
-
52
- #
53
- # Class composition
54
- #
55
- element :country, 'Country', :tag => 'country'
56
-
57
- attribute :occupied, Boolean
58
-
59
- def initialize(parameters)
60
- parameters.each_pair do |property,value|
61
- send("#{property}=",value) if respond_to?("#{property}=")
62
- end
63
- @modified = @temporary = true
64
- end
65
-
66
- end
67
-
68
- #
69
- # Country is composed above the in Address class. Here is a demonstration
70
- # of how to_xml will handle class composition as well as utilizing the tag
71
- # value.
72
- #
73
- class Country
74
- include HappyMapper
75
-
76
- attribute :code, String, :tag => 'countryCode'
77
- has_one :name, String, :tag => 'countryName'
78
- has_one :description, 'Description', :tag => 'description'
79
-
80
- #
81
- # This inner-class here is to demonstrate saving a text node
82
- # and optional attributes
83
- #
84
- class Description
85
- include HappyMapper
86
- content :description, String
87
- attribute :category, String, :tag => 'category'
88
- attribute :rating, String, :tag => 'rating', :state_when_nil => true
89
-
90
- def initialize(desc)
91
- @description = desc
92
- end
93
- end
94
-
95
- def initialize(parameters)
96
- parameters.each_pair do |property,value|
97
- send("#{property}=",value) if respond_to?("#{property}=")
98
- end
99
- end
100
-
101
- end
102
-
103
- describe HappyMapper do
104
-
105
- context "#to_xml" do
106
-
107
- before(:all) do
108
- address = Address.new('street' => 'Mockingbird Lane',
109
- 'location' => 'Home',
110
- 'housenumber' => '1313',
111
- 'postcode' => '98103',
112
- 'city' => 'Seattle',
113
- 'country' => Country.new(:name => 'USA', :code => 'us', :empty_code => nil,
114
- :description => Country::Description.new("A lovely country") ),
115
- 'date_created' => '2011-01-01 15:00:00',
116
- 'occupied' => false)
117
-
118
-
119
- address.dates_updated = ["2011-01-01 16:01:00","2011-01-02 11:30:01"]
120
-
121
- @address_xml = Nokogiri::XML(address.to_xml).root
122
- end
123
-
124
- it "should save elements" do
125
- { 'street' => 'Mockingbird Lane',
126
- 'postcode' => '98103',
127
- 'city' => 'Seattle' }.each_pair do |property,value|
128
-
129
- @address_xml.xpath("#{property}").text.should == value
130
-
131
- end
132
- end
133
-
134
- it "should save the element with the result of a function call and not the value of the instance variable" do
135
- @address_xml.xpath("housenumber").text.should == "[1313]"
136
- end
137
-
138
- it "should not save elements marked as read_only" do
139
- @address_xml.xpath('temporary').should be_empty
140
- end
141
-
142
- it "should save attribues" do
143
- @address_xml.xpath('@location').text.should == "Home-live"
144
- end
145
-
146
- it "should not save attributes marked as read_only" do
147
- @address_xml.xpath("@modified").should be_empty
148
- end
149
-
150
- it 'should save attributes that are Boolean and have a value of false' do
151
- @address_xml.xpath('@occupied').text.should == "false"
152
- end
153
-
154
- context "state_when_nil option" do
155
-
156
- it "should save an empty element" do
157
- @address_xml.xpath('description').text.should == ""
158
- end
159
-
160
- end
161
-
162
- context "on_save option" do
163
-
164
- it "should save the result of the lambda" do
165
- @address_xml.xpath('date_created').text.should == "15:00:00 01/01/11"
166
- end
167
-
168
- it "should save the result of a method" do
169
- @address_xml.xpath('@location').text.should == "Home-live"
170
- end
171
-
172
- end
173
-
174
-
175
- it "should save elements defined with the 'has_many' relationship" do
176
- dates_updated = @address_xml.xpath('dates_updated')
177
- dates_updated.length.should == 2
178
- dates_updated.first.text.should == "16:01:00 01/01/11"
179
- dates_updated.last.text.should == "11:30:01 01/02/11"
180
- end
181
-
182
- context "class types that also contain HappyMapper mappings" do
183
-
184
- it "should save attributes" do
185
- @address_xml.xpath('country/@countryCode').text.should == "us"
186
- end
187
-
188
- it "should save elements" do
189
- @address_xml.xpath('country/countryName').text.should == "USA"
190
- end
191
-
192
- it "should save elements" do
193
- @address_xml.xpath('country/description').text.should == "A lovely country"
194
- end
195
-
196
- end
197
-
198
- end
199
-
200
-
201
- end
202
-
203
- end
@@ -1,69 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- module Wrap
4
- class SubClass
5
- include HappyMapper
6
- tag 'subclass'
7
- attribute :myattr, String
8
- has_many :items, String, :tag => 'item'
9
- end
10
- class Root
11
- include HappyMapper
12
- tag 'root'
13
- attribute :attr1, String
14
- element :name, String
15
- wrap 'mywraptag' do
16
- element :description, String
17
- has_one :subclass, SubClass
18
- end
19
- element :number, Integer
20
- end
21
- end
22
-
23
- describe HappyMapper do
24
- describe "can parse and #to_xml taking into account a holder tag that won't be defined as a HappyMapper class" do
25
-
26
- it 'should parse xml' do
27
- root = Wrap::Root.parse(fixture_file('wrapper.xml'))
28
- root.attr1.should == 'somevalue'
29
- root.name.should == 'myname'
30
- root.description.should == 'some description'
31
- root.subclass.myattr.should == 'attrvalue'
32
- root.subclass.items.should have(2).items
33
- root.subclass.items[0].should == 'item1'
34
- root.subclass.items[1].should == 'item2'
35
- root.number.should == 12345
36
- end
37
-
38
- it "should initialize anonymous classes so nil class values don't occur" do
39
- root = Wrap::Root.new
40
- lambda { root.description = 'anything' }.should_not raise_error
41
- end
42
-
43
- it 'should #to_xml with wrapped tag' do
44
- root = Wrap::Root.new
45
- root.attr1 = 'somevalue'
46
- root.name = 'myname'
47
- root.description = 'some description'
48
- root.number = 12345
49
-
50
- subclass = Wrap::SubClass.new
51
- subclass.myattr = 'attrvalue'
52
- subclass.items = []
53
- subclass.items << 'item1'
54
- subclass.items << 'item2'
55
-
56
- root.subclass = subclass
57
-
58
- xml = Nokogiri::XML(root.to_xml)
59
- xml.xpath('/root/@attr1').text.should == 'somevalue'
60
- xml.xpath('/root/name').text.should == 'myname'
61
- xml.xpath('/root/mywraptag/description').text.should == 'some description'
62
- xml.xpath('/root/mywraptag/subclass/@myattr').text.should == 'attrvalue'
63
- xml.xpath('/root/mywraptag/subclass/item').should have(2).items
64
- xml.xpath('/root/mywraptag/subclass/item[1]').text.should == 'item1'
65
- xml.xpath('/root/mywraptag/subclass/item[2]').text.should == 'item2'
66
- xml.xpath('/root/number').text.should == '12345'
67
- end
68
- end
69
- end