nokogiri-happymapper 0.5.3 → 0.5.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +13 -0
- data/lib/happymapper.rb +63 -10
- data/spec/fixtures/wrapper.xml +11 -0
- data/spec/happymapper_generic_base_spec.rb +92 -0
- data/spec/happymapper_wrap_spec.rb +69 -0
- metadata +17 -4
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
## 0.5.4/ 2012-09-25
|
2
|
+
|
3
|
+
* #wrap method allows you to better model xml content that is buried deep
|
4
|
+
within the xml. This implementation addresses issues with calling #to_xml
|
5
|
+
with content that was parsed from an xpath. (zrob)
|
6
|
+
|
7
|
+
* Parent HappyMapper classes may dictate the name of the tag for the child
|
8
|
+
HappyMapper instances. (zrob)
|
9
|
+
|
10
|
+
## 0.5.3/ 2012-09-23
|
11
|
+
|
12
|
+
* String is the default type for parsed fields. (crv)
|
13
|
+
* Update the attributes of an existing HappyMapper instance with new XML (benoist)
|
data/lib/happymapper.rb
CHANGED
@@ -7,12 +7,15 @@ class XmlContent; end
|
|
7
7
|
|
8
8
|
module HappyMapper
|
9
9
|
|
10
|
+
VERSION = "0.5.4"
|
11
|
+
|
10
12
|
DEFAULT_NS = "happymapper"
|
11
13
|
|
12
14
|
def self.included(base)
|
13
15
|
base.instance_variable_set("@attributes", {})
|
14
16
|
base.instance_variable_set("@elements", {})
|
15
17
|
base.instance_variable_set("@registered_namespaces", {})
|
18
|
+
base.instance_variable_set("@wrapper_anonymous_classes", {})
|
16
19
|
|
17
20
|
base.extend ClassMethods
|
18
21
|
end
|
@@ -196,6 +199,38 @@ module HappyMapper
|
|
196
199
|
def tag_name
|
197
200
|
@tag_name ||= to_s.split('::')[-1].downcase
|
198
201
|
end
|
202
|
+
|
203
|
+
# There is an XML tag that needs to be known for parsing and should be generated
|
204
|
+
# during a to_xml. But it doesn't need to be a class and the contained elements should
|
205
|
+
# be made available on the parent class
|
206
|
+
#
|
207
|
+
# @param [String] name the name of the element that is just a place holder
|
208
|
+
# @param [Proc] blk the element definitions inside the place holder tag
|
209
|
+
#
|
210
|
+
def wrap(name, &blk)
|
211
|
+
# Get an anonymous HappyMapper that has 'name' as its tag and defined
|
212
|
+
# in '&blk'. Then save that to a class instance variable for later use
|
213
|
+
wrapper = AnonymousWrapperClassFactory.get(name, &blk)
|
214
|
+
@wrapper_anonymous_classes[wrapper.inspect] = wrapper
|
215
|
+
|
216
|
+
# Create getter/setter for each element and attribute defined on the anonymous HappyMapper
|
217
|
+
# onto this class. They get/set the value by passing thru to the anonymous class.
|
218
|
+
passthrus = wrapper.attributes + wrapper.elements
|
219
|
+
passthrus.each do |item|
|
220
|
+
class_eval %{
|
221
|
+
def #{item.method_name}
|
222
|
+
@#{name} ||= self.class.instance_variable_get('@wrapper_anonymous_classes')['#{wrapper.inspect}'].new
|
223
|
+
@#{name}.#{item.method_name}
|
224
|
+
end
|
225
|
+
def #{item.method_name}=(value)
|
226
|
+
@#{name} ||= self.class.instance_variable_get('@wrapper_anonymous_classes')['#{wrapper.inspect}'].new
|
227
|
+
@#{name}.#{item.method_name} = value
|
228
|
+
end
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
232
|
+
has_one name, wrapper
|
233
|
+
end
|
199
234
|
|
200
235
|
#
|
201
236
|
# @param [Nokogiri::XML::Node,Nokogiri:XML::Document,String] xml the XML
|
@@ -389,13 +424,17 @@ module HappyMapper
|
|
389
424
|
# is being used when called recursively.
|
390
425
|
# @param [String] default_namespace the name of the namespace which is the
|
391
426
|
# default for the xml being produced; this is specified by the element
|
392
|
-
# declaration when calling #to_xml recursively.
|
427
|
+
# declaration when calling #to_xml recursively.
|
428
|
+
# @param [String] tag_from_parent the xml tag to use on the element when being
|
429
|
+
# called recursively. This lets the parent doc define its own structure.
|
430
|
+
# Otherwise the element uses the tag it has defined for itself. Should only
|
431
|
+
# apply when calling a child HappyMapper element.
|
393
432
|
#
|
394
433
|
# @return [String,Nokogiri::XML::Builder] return XML representation of the
|
395
434
|
# HappyMapper object; when called recursively this is going to return
|
396
435
|
# and Nokogiri::XML::Builder object.
|
397
436
|
#
|
398
|
-
def to_xml(builder = nil,default_namespace = nil)
|
437
|
+
def to_xml(builder = nil,default_namespace = nil,tag_from_parent = nil)
|
399
438
|
|
400
439
|
#
|
401
440
|
# If to_xml has been called without a passed in builder instance that
|
@@ -454,12 +493,13 @@ module HappyMapper
|
|
454
493
|
end.flatten
|
455
494
|
|
456
495
|
attributes = Hash[ *attributes ]
|
457
|
-
|
496
|
+
|
458
497
|
#
|
459
|
-
# Create a tag in the builder that matches the class's tag name
|
498
|
+
# Create a tag in the builder that matches the class's tag name unless a tag was passed
|
499
|
+
# in a recursive call from the parent doc. Then append
|
460
500
|
# any attributes to the element that were defined above.
|
461
501
|
#
|
462
|
-
builder.send("#{self.class.tag_name}_",attributes) do |xml|
|
502
|
+
builder.send("#{tag_from_parent || self.class.tag_name}_",attributes) do |xml|
|
463
503
|
|
464
504
|
#
|
465
505
|
# Add all the registered namespaces to the root element.
|
@@ -575,7 +615,7 @@ module HappyMapper
|
|
575
615
|
# process should have their contents retrieved and attached
|
576
616
|
# to the builder structure
|
577
617
|
#
|
578
|
-
item.to_xml(xml,element.options[:namespace])
|
618
|
+
item.to_xml(xml,element.options[:namespace],element.options[:tag] || nil)
|
579
619
|
|
580
620
|
elsif item
|
581
621
|
|
@@ -624,11 +664,24 @@ module HappyMapper
|
|
624
664
|
# Params and return are the same as the class parse() method above.
|
625
665
|
def parse(xml, options = {})
|
626
666
|
self.class.parse(xml, options.merge!(:update => self))
|
667
|
+
end
|
668
|
+
|
669
|
+
private
|
670
|
+
|
671
|
+
# Factory for creating anonmyous HappyMappers
|
672
|
+
class AnonymousWrapperClassFactory
|
673
|
+
def self.get(name, &blk)
|
674
|
+
Class.new do
|
675
|
+
include HappyMapper
|
676
|
+
tag name
|
677
|
+
instance_eval &blk
|
678
|
+
end
|
679
|
+
end
|
627
680
|
end
|
628
681
|
|
629
682
|
end
|
630
683
|
|
631
|
-
require 'happymapper/item'
|
632
|
-
require 'happymapper/attribute'
|
633
|
-
require 'happymapper/element'
|
634
|
-
require 'happymapper/text_node'
|
684
|
+
require File.dirname(__FILE__) + '/happymapper/item'
|
685
|
+
require File.dirname(__FILE__) + '/happymapper/attribute'
|
686
|
+
require File.dirname(__FILE__) + '/happymapper/element'
|
687
|
+
require File.dirname(__FILE__) + '/happymapper/text_node'
|
@@ -0,0 +1,92 @@
|
|
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
|
@@ -0,0 +1,69 @@
|
|
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
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nokogiri-happymapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date:
|
17
|
+
date: 2011-08-22 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: nokogiri
|
@@ -50,11 +50,12 @@ dependencies:
|
|
50
50
|
version: '2.8'
|
51
51
|
description: Object to XML Mapping Library, using Nokogiri (fork from John Nunemaker's
|
52
52
|
Happymapper)
|
53
|
-
email:
|
53
|
+
email: franklin.webber@gmail.com
|
54
54
|
executables: []
|
55
55
|
extensions: []
|
56
56
|
extra_rdoc_files:
|
57
57
|
- README.md
|
58
|
+
- CHANGELOG.md
|
58
59
|
- TODO
|
59
60
|
files:
|
60
61
|
- lib/happymapper.rb
|
@@ -63,6 +64,7 @@ files:
|
|
63
64
|
- lib/happymapper/item.rb
|
64
65
|
- lib/happymapper/text_node.rb
|
65
66
|
- README.md
|
67
|
+
- CHANGELOG.md
|
66
68
|
- TODO
|
67
69
|
- spec/fixtures/address.xml
|
68
70
|
- spec/fixtures/ambigous_items.xml
|
@@ -88,20 +90,28 @@ files:
|
|
88
90
|
- spec/fixtures/radar.xml
|
89
91
|
- spec/fixtures/statuses.xml
|
90
92
|
- spec/fixtures/subclass_namespace.xml
|
93
|
+
- spec/fixtures/wrapper.xml
|
91
94
|
- spec/happymapper_attribute_spec.rb
|
92
95
|
- spec/happymapper_element_spec.rb
|
96
|
+
- spec/happymapper_generic_base_spec.rb
|
93
97
|
- spec/happymapper_item_spec.rb
|
94
98
|
- spec/happymapper_spec.rb
|
95
99
|
- spec/happymapper_text_node_spec.rb
|
96
100
|
- spec/happymapper_to_xml_namespaces_spec.rb
|
97
101
|
- spec/happymapper_to_xml_spec.rb
|
102
|
+
- spec/happymapper_wrap_spec.rb
|
98
103
|
- spec/ignay_spec.rb
|
99
104
|
- spec/parse_instance_spec.rb
|
100
105
|
- spec/spec_helper.rb
|
101
106
|
- spec/xpath_spec.rb
|
102
107
|
homepage: http://github.com/dam5s/happymapper
|
103
108
|
licenses: []
|
104
|
-
post_install_message:
|
109
|
+
post_install_message: ! "\n Thank you for installing nokogiri-happymapper 0.5.4 /
|
110
|
+
2012-09-25.\n \n Changes:\n \n * #wrap method allows you to better model xml
|
111
|
+
content that is buried deep\n within the xml. This implementation addresses issues
|
112
|
+
with calling #to_xml\n with content that was parsed from an xpath. (zrob)\n \n
|
113
|
+
\ * Parent HappyMapper classes may dictate the name of the tag for the child\n HappyMapper
|
114
|
+
instances. (zrob)\n \n\n\n"
|
105
115
|
rdoc_options: []
|
106
116
|
require_paths:
|
107
117
|
- lib
|
@@ -148,13 +158,16 @@ test_files:
|
|
148
158
|
- spec/fixtures/radar.xml
|
149
159
|
- spec/fixtures/statuses.xml
|
150
160
|
- spec/fixtures/subclass_namespace.xml
|
161
|
+
- spec/fixtures/wrapper.xml
|
151
162
|
- spec/happymapper_attribute_spec.rb
|
152
163
|
- spec/happymapper_element_spec.rb
|
164
|
+
- spec/happymapper_generic_base_spec.rb
|
153
165
|
- spec/happymapper_item_spec.rb
|
154
166
|
- spec/happymapper_spec.rb
|
155
167
|
- spec/happymapper_text_node_spec.rb
|
156
168
|
- spec/happymapper_to_xml_namespaces_spec.rb
|
157
169
|
- spec/happymapper_to_xml_spec.rb
|
170
|
+
- spec/happymapper_wrap_spec.rb
|
158
171
|
- spec/ignay_spec.rb
|
159
172
|
- spec/parse_instance_spec.rb
|
160
173
|
- spec/spec_helper.rb
|