peachy 0.2.0 → 0.2.1
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.
- data/lib/no_xml_parser_available.rb +10 -0
- data/lib/peachy/childless_proxy_with_attributes.rb +3 -4
- data/lib/peachy/convention_checks.rb +6 -0
- data/lib/peachy/method_mask.rb +1 -0
- data/lib/peachy/morph_into_array.rb +1 -1
- data/lib/peachy/my_meta_class.rb +1 -0
- data/lib/peachy/parsers/nokogiri_wrapper.rb +73 -0
- data/lib/peachy/proxy.rb +23 -71
- data/lib/peachy/proxy_factory.rb +34 -0
- data/lib/peachy/version.rb +1 -1
- data/lib/peachy/xml_node.rb +20 -0
- data/lib/peachy/xml_parser_factory.rb +15 -0
- data/lib/peachy.rb +10 -1
- data/spec/attributes_on_a_parent_node_spec.rb +6 -0
- data/spec/camel_case_names_spec.rb +13 -1
- data/spec/collections_with_children_as_arrays_spec.rb +2 -0
- data/spec/hyphen_separated_names_spec.rb +29 -2
- data/spec/libxml_is_the_available_xml_parser_spec.rb +30 -0
- data/spec/no_xml_parsers_are_available_spec.rb +13 -0
- data/spec/nokogiri_is_the_available_xml_parser_spec.rb +25 -0
- data/spec/pascal_case_names_spec.rb +18 -1
- data/spec/peachy_parsers_nokogiri_spec.rb +28 -0
- data/spec/spec_helper.rb +2 -0
- metadata +12 -4
- data/lib/peachy/node_child_matcher.rb +0 -22
@@ -1,16 +1,15 @@
|
|
1
1
|
module Peachy
|
2
2
|
class ChildlessProxyWithAttributes < Proxy
|
3
|
+
# Returns the text content of the XML node encapsulated by this instance.
|
3
4
|
def value
|
4
5
|
acts_as_only_child
|
5
|
-
|
6
|
+
node.content
|
6
7
|
end
|
7
8
|
|
8
9
|
private
|
9
10
|
def generate_method_for_xml method_name
|
10
11
|
check_for_convention(method_name)
|
11
|
-
match
|
12
|
-
raise NoMatchingXmlPart.new method_name, node_name if match.nil?
|
13
|
-
return create_value(match) {|child| define_child method_name, child }
|
12
|
+
create_method_for_attribute(method_name) {|match| no_matching_xml(method_name) if match.nil? }
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
module Peachy
|
2
2
|
module ConventionChecks
|
3
|
+
private
|
4
|
+
# Checks whether the provided method name is in the accepted convention,
|
5
|
+
# raising a MethodNotInRubyConvention if it's not.
|
3
6
|
def check_for_convention method_name
|
4
7
|
raise MethodNotInRubyConvention.new(method_name) unless matches_convention(method_name)
|
5
8
|
end
|
6
9
|
|
10
|
+
# Checks whether the given method name matches the Ruby convention of
|
11
|
+
# lowercase with underscores. This method does not allow question marks,
|
12
|
+
# excalmation marks or numbers, however.
|
7
13
|
def matches_convention method_name
|
8
14
|
method_name.to_s =~ /^[a-z]+(?:_[a-z]+){0,}$/
|
9
15
|
end
|
data/lib/peachy/method_mask.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Peachy
|
2
2
|
module MorphIntoArray
|
3
|
+
private
|
3
4
|
def you_use_me_like_an_array method_name, block_given, *args
|
4
5
|
return ((block_given or args.size > 0) and array_can?(method_name))
|
5
|
-
#method_name == :[] and args.one? and args.first == 0
|
6
6
|
end
|
7
7
|
|
8
8
|
def array_can? method_name
|
data/lib/peachy/my_meta_class.rb
CHANGED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Peachy
|
2
|
+
module Parsers
|
3
|
+
class NokogiriWrapper
|
4
|
+
def initialize nokogiri
|
5
|
+
@nokogiri = nokogiri
|
6
|
+
end
|
7
|
+
|
8
|
+
# Runs the XPath for the method name against the underlying XML DOM,
|
9
|
+
# returning nil if no element or attribute matching the method name is found
|
10
|
+
# in the children of the current location in the DOM.
|
11
|
+
def find_matches method_name
|
12
|
+
matches = xpath(xpath_for(method_name))
|
13
|
+
return nil if matches.length < 1
|
14
|
+
return matches
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_match_by_attributes method_name
|
18
|
+
mapped = method_name.variations.map {|variation| attribute(variation) }
|
19
|
+
mapped.find {|match| match != nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_attribute method_name
|
23
|
+
attribute(method_name.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_children_and_attributes?
|
27
|
+
there_are_child_nodes? and node_has_attributes?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Determines whether the given element contains any child elements or not.
|
31
|
+
# The choice of implementation is based on performance tests between using
|
32
|
+
# XPath and a Ruby iterator.
|
33
|
+
def there_are_child_nodes?
|
34
|
+
children.any? {|child| child.kind_of? Peachy::Parsers::NokogiriWrapper }
|
35
|
+
end
|
36
|
+
|
37
|
+
def node_has_attributes?
|
38
|
+
attribute_nodes.size > 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def content
|
42
|
+
@nokogiri.content
|
43
|
+
end
|
44
|
+
|
45
|
+
def name
|
46
|
+
@nokogiri.name
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def attribute_nodes
|
51
|
+
@nokogiri.attribute_nodes.map {|attribute| attribute.content }
|
52
|
+
end
|
53
|
+
|
54
|
+
def children
|
55
|
+
@nokogiri.children.map {|child| NokogiriWrapper.new(child) if child.kind_of? Nokogiri::XML::Element }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Gets the XPath for all variations of the MethodName instance
|
59
|
+
def xpath_for method_name
|
60
|
+
method_name.variations.map {|variation| "./#{variation}" } * '|'
|
61
|
+
end
|
62
|
+
|
63
|
+
def xpath xpath
|
64
|
+
@nokogiri.xpath(xpath).map{|noko_node| NokogiriWrapper.new(noko_node) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def attribute attribute_name
|
68
|
+
noko = @nokogiri.attribute(attribute_name)
|
69
|
+
noko.nil?? nil : NokogiriWrapper.new(noko)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/peachy/proxy.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'nokogiri'
|
3
|
-
|
4
1
|
module Peachy
|
5
2
|
class Proxy
|
6
3
|
alias_method :original_method_missing, :method_missing
|
7
4
|
extend MethodMask
|
8
|
-
include ConventionChecks, MorphIntoArray, MyMetaClass,
|
5
|
+
include ConventionChecks, MorphIntoArray, MyMetaClass, XmlNode
|
9
6
|
|
10
7
|
# This hides all public methods on the class except for 'methods', 'nil?'
|
11
8
|
# 'respond_to?' and 'inspect', which I've found are too useful to hide for
|
@@ -14,9 +11,9 @@ module Peachy
|
|
14
11
|
|
15
12
|
# Takes either a string containing XML or a Nokogiri::XML::Element as the
|
16
13
|
# single argument.
|
17
|
-
def initialize
|
18
|
-
@xml =
|
19
|
-
@nokogiri_node =
|
14
|
+
def initialize xml_node
|
15
|
+
@xml = xml_node if xml_node.kind_of? String
|
16
|
+
@nokogiri_node = xml_node if xml_node.kind_of? Peachy::Parsers::NokogiriWrapper #Nokogiri::XML::Element
|
20
17
|
end
|
21
18
|
|
22
19
|
# Overloaded so that calls to methods representative of an XML element or
|
@@ -82,81 +79,45 @@ module Peachy
|
|
82
79
|
acts_as_only_child
|
83
80
|
child_proxy
|
84
81
|
elsif array_can?(method_name)
|
85
|
-
#
|
86
|
-
|
87
|
-
new_proxy = create_from_element(nokogiri_node)
|
82
|
+
# morph into an array, as method is a zero-length array call
|
83
|
+
new_proxy = ProxyFactory.create_from_element(node)
|
88
84
|
morph_into_array(new_proxy, method_name)
|
89
85
|
else
|
90
|
-
|
91
|
-
raise NoMatchingXmlPart.new(method_name, node_name)
|
86
|
+
no_matching_xml(method_name)
|
92
87
|
end
|
93
88
|
end
|
94
89
|
|
95
90
|
private
|
96
91
|
def generate_method_for_xml method_name
|
97
92
|
check_for_convention(method_name)
|
98
|
-
attribute_content =
|
93
|
+
attribute_content = create_attribute method_name
|
99
94
|
return attribute_content unless attribute_content.nil?
|
100
|
-
matches = find_matches(method_name
|
95
|
+
matches = node.find_matches(method_name)
|
101
96
|
matches.nil? ? nil : create_method_for_child_or_content(method_name, matches)
|
102
97
|
end
|
103
98
|
|
104
99
|
def create_method_for_child_or_content method_name, matches
|
105
100
|
return create_from_element_list(method_name, matches) if matches.size > 1
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def create_from_parent_with_attribute method_name, node
|
110
|
-
if there_are_child_nodes?(node) and node_has_attributes?(node)
|
111
|
-
match = node.attribute(method_name.to_s)
|
112
|
-
create_value(match) {|child| define_child(method_name, child) } unless match.nil?
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def create_from_element_list method_name, matches
|
117
|
-
define_method(method_name) { return matches_to_array matches }
|
118
|
-
end
|
119
|
-
|
120
|
-
def matches_to_array matches
|
121
|
-
matches.inject([]) {|array, child| array << create_from_element(child) }
|
122
|
-
end
|
123
|
-
|
124
|
-
def create_from_element match, &block
|
125
|
-
return create_proxy(match, &block) if there_are_child_nodes?(match)
|
126
|
-
return create_proxy_with_attributes(match, &block) if node_has_attributes?(match)
|
127
|
-
return create_content_child(match, &block)
|
101
|
+
child = ProxyFactory.create_from_element(matches[0])
|
102
|
+
define_child(method_name, child)
|
128
103
|
end
|
129
104
|
|
130
|
-
def
|
131
|
-
|
105
|
+
def create_attribute method_name
|
106
|
+
create_method_for_attribute(method_name) if node.has_children_and_attributes?
|
132
107
|
end
|
133
108
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
match.children.any? {|child| child.kind_of? Nokogiri::XML::Element }
|
109
|
+
def create_method_for_attribute method_name
|
110
|
+
match = node.find_match_by_attributes(method_name)
|
111
|
+
yield match if block_given?
|
112
|
+
define_child(method_name, match.content) unless match.nil?
|
139
113
|
end
|
140
114
|
|
141
|
-
def
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
def create_content_child match, &block
|
146
|
-
create_child(SimpleContent.new(match.content, match.name), &block)
|
147
|
-
end
|
148
|
-
|
149
|
-
def create_proxy match, &block
|
150
|
-
create_child(Proxy.new(match), &block)
|
151
|
-
end
|
152
|
-
|
153
|
-
def create_proxy_with_attributes match, &block
|
154
|
-
create_child ChildlessProxyWithAttributes.new(match), &block
|
115
|
+
def create_from_element_list method_name, matches
|
116
|
+
define_method(method_name) { return matches_to_array(matches) }
|
155
117
|
end
|
156
118
|
|
157
|
-
def
|
158
|
-
|
159
|
-
return child
|
119
|
+
def matches_to_array matches
|
120
|
+
matches.inject([]) {|array, child| array << ProxyFactory.create_from_element(child) }
|
160
121
|
end
|
161
122
|
|
162
123
|
def define_child method_name, child
|
@@ -172,17 +133,8 @@ module Peachy
|
|
172
133
|
@xml.nil? and @nokogiri_node.nil?
|
173
134
|
end
|
174
135
|
|
175
|
-
def
|
176
|
-
|
177
|
-
end
|
178
|
-
|
179
|
-
def nokogiri_node
|
180
|
-
raise InvalidProxyParameters.new(:xml => nil, :nokogiri => nil) if variables_are_nil?
|
181
|
-
@nokogiri_node ||= Nokogiri::XML(@xml)
|
182
|
-
end
|
183
|
-
|
184
|
-
def clone
|
185
|
-
create_from_element(nokogiri_node)
|
136
|
+
def no_matching_xml method_name
|
137
|
+
raise NoMatchingXmlPart.new(method_name, node_name)
|
186
138
|
end
|
187
139
|
end
|
188
140
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Peachy
|
2
|
+
class ProxyFactory
|
3
|
+
class << self
|
4
|
+
def create_from_element match
|
5
|
+
return create_proxy(match) if there_are_child_nodes?(match)
|
6
|
+
return create_proxy_with_attributes(match) if node_has_attributes?(match)
|
7
|
+
return create_content_child(match)
|
8
|
+
end
|
9
|
+
|
10
|
+
def node_has_attributes? match
|
11
|
+
match.node_has_attributes?
|
12
|
+
end
|
13
|
+
|
14
|
+
# Determines whether the given element contains any child elements or not.
|
15
|
+
# The choice of implementation is based on performance tests between using
|
16
|
+
# XPath and a Ruby iterator.
|
17
|
+
def there_are_child_nodes? match
|
18
|
+
match.there_are_child_nodes?
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_content_child match
|
22
|
+
SimpleContent.new(match.content, match.name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_proxy match
|
26
|
+
Proxy.new(match)
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_proxy_with_attributes match
|
30
|
+
ChildlessProxyWithAttributes.new(match)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/peachy/version.rb
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Peachy
|
2
|
+
module XmlNode
|
3
|
+
private
|
4
|
+
def clone
|
5
|
+
ProxyFactory.create_from_element(node)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the name of the encapsulated node.
|
9
|
+
def node_name
|
10
|
+
node.name
|
11
|
+
end
|
12
|
+
|
13
|
+
# The encapsulated Nokogiri node, which is lazy loaded from the @xml instance
|
14
|
+
# variable.
|
15
|
+
def node
|
16
|
+
raise InvalidProxyParameters.new(:xml => nil, :nokogiri => nil) if variables_are_nil?
|
17
|
+
@nokogiri_node ||= Peachy::Parsers::NokogiriWrapper.new(Nokogiri::XML(@xml))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Peachy
|
2
|
+
class XmlParserFactory
|
3
|
+
def load_parser
|
4
|
+
return load_up(:nokogiri) if Gem.available? /nokogiri/
|
5
|
+
return load_up(:libxml) if Gem.available? /libxml/
|
6
|
+
raise NoXmlParserAvailable.new
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
def load_up xml_parser
|
11
|
+
require(xml_parser.to_s)
|
12
|
+
return xml_parser
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/peachy.rb
CHANGED
@@ -1,18 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
1
3
|
require File.join(File.dirname(__FILE__), 'already_an_only_child')
|
2
4
|
require File.join(File.dirname(__FILE__), 'invalid_proxy_parameters')
|
3
5
|
require File.join(File.dirname(__FILE__), 'method_not_in_ruby_convention')
|
4
6
|
require File.join(File.dirname(__FILE__), 'no_matching_xml_part')
|
7
|
+
require File.join(File.dirname(__FILE__), 'no_xml_parser_available')
|
5
8
|
require File.join(File.dirname(__FILE__), 'peachy/convention_checks')
|
6
9
|
require File.join(File.dirname(__FILE__), 'peachy/string_styler')
|
7
10
|
require File.join(File.dirname(__FILE__), 'peachy/method_name')
|
8
11
|
require File.join(File.dirname(__FILE__), 'peachy/method_mask')
|
9
12
|
require File.join(File.dirname(__FILE__), 'peachy/morph_into_array')
|
10
13
|
require File.join(File.dirname(__FILE__), 'peachy/my_meta_class')
|
11
|
-
require File.join(File.dirname(__FILE__), 'peachy/
|
14
|
+
require File.join(File.dirname(__FILE__), 'peachy/xml_node')
|
12
15
|
require File.join(File.dirname(__FILE__), 'peachy/simple_content')
|
16
|
+
require File.join(File.dirname(__FILE__), 'peachy/xml_parser_factory')
|
17
|
+
require File.join(File.dirname(__FILE__), 'peachy/parsers/nokogiri_wrapper')
|
13
18
|
require File.join(File.dirname(__FILE__), 'peachy/proxy')
|
19
|
+
require File.join(File.dirname(__FILE__), 'peachy/proxy_factory')
|
14
20
|
require File.join(File.dirname(__FILE__), 'peachy/childless_proxy_with_attributes')
|
15
21
|
|
22
|
+
# first up, load the underlying XML parser that Peachy will use
|
23
|
+
Peachy::XmlParserFactory.new.load_parser
|
24
|
+
|
16
25
|
module Peachy
|
17
26
|
def self.whine
|
18
27
|
@whine = true
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
1
3
|
describe "attributes on a parent node" do
|
2
4
|
before(:each) do
|
3
5
|
@proxy = Peachy::Proxy.new '<root><test_node name="Test"><child>Check meh.</child><test_node></root>'
|
@@ -15,4 +17,8 @@ describe "attributes on a parent node" do
|
|
15
17
|
@proxy.root.test_node.name
|
16
18
|
@proxy.root.test_node.methods.should include 'name'
|
17
19
|
end
|
20
|
+
|
21
|
+
it "should raise an error if the attirbute does not exist" do
|
22
|
+
lambda { @proxy.root.test_node.other }.should raise_error NoMatchingXmlPart
|
23
|
+
end
|
18
24
|
end
|
@@ -1,6 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
describe "interpreting element and attribute names that are defined in camelCase" do
|
2
3
|
before(:each) do
|
3
|
-
@proxy = Peachy::Proxy.new
|
4
|
+
@proxy = Peachy::Proxy.new <<XML
|
5
|
+
<root>
|
6
|
+
<testNode>Check meh.</testNode>
|
7
|
+
<secondNode id="2" recordLabel="Wall of Sound">Check meh, too.</secondNode>
|
8
|
+
<thirdNode id="2" recordLabel="Wall of Sound"><child>Nested</child></secondNode>
|
9
|
+
</root>
|
10
|
+
XML
|
4
11
|
end
|
5
12
|
|
6
13
|
it "should match a method to an element by camel case" do
|
@@ -20,5 +27,10 @@ describe "interpreting element and attribute names that are defined in camelCase
|
|
20
27
|
@proxy.root.second_node.record_label
|
21
28
|
@proxy.root.second_node.methods.should include 'record_label'
|
22
29
|
end
|
30
|
+
|
31
|
+
it "should match parent attribute names" do
|
32
|
+
@proxy.root.third_node.record_label.should == 'Wall of Sound'
|
33
|
+
@proxy.root.third_node.methods.should include 'record_label'
|
34
|
+
end
|
23
35
|
end
|
24
36
|
|
@@ -1,15 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
1
3
|
describe "interpretting element names that contain hyphens" do
|
2
4
|
before(:each) do
|
3
|
-
@proxy = Peachy::Proxy.new
|
5
|
+
@proxy = Peachy::Proxy.new <<XML
|
6
|
+
<test-node>
|
7
|
+
<first-child>Check meh.</first-child>
|
8
|
+
<second-child record-label="Rough Trade">Check meh, too.</second-child>
|
9
|
+
<third-child record-label="Rough Trade"><text-node>Check meh again.</text-node></third-child>
|
10
|
+
</test-node>
|
11
|
+
XML
|
4
12
|
end
|
5
13
|
|
6
14
|
it "should try to match a method to a node with hyphens" do
|
7
|
-
@proxy.test_node.value.should == 'Check meh.'
|
15
|
+
@proxy.test_node.first_child.value.should == 'Check meh.'
|
8
16
|
end
|
9
17
|
|
10
18
|
it "should define a method for the element name" do
|
11
19
|
@proxy.test_node
|
12
20
|
@proxy.methods.should include 'test_node'
|
13
21
|
end
|
22
|
+
|
23
|
+
it "should match a method to an attribute by pascal case" do
|
24
|
+
@proxy.test_node.second_child.record_label.should == 'Rough Trade'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should define a method from pascal cased attribute name" do
|
28
|
+
@proxy.test_node.second_child.record_label
|
29
|
+
@proxy.test_node.second_child.methods.should include 'record_label'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should define a method on a parent with attributes" do
|
33
|
+
@proxy.test_node.third_child.record_label.should == 'Rough Trade'
|
34
|
+
@proxy.test_node.third_child.methods.should include 'record_label'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should allow child nodes to be selected after an attrbiute is selected on a parent node" do
|
38
|
+
@proxy.test_node.third_child.record_label.should == 'Rough Trade'
|
39
|
+
@proxy.test_node.third_child.text_node.value.should == 'Check meh again.'
|
40
|
+
end
|
14
41
|
end
|
15
42
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Peachy::XmlParserFactory do
|
4
|
+
before(:each) do
|
5
|
+
Gem.stubs(:available?).with(/libxml/).returns(true)
|
6
|
+
Gem.stubs(:available?).with(/nokogiri/).returns(false)
|
7
|
+
@factory = Peachy::XmlParserFactory.new
|
8
|
+
@factory.stubs(:require).with('libxml').returns(true)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return LibXML if Nokogiri is not an available gem" do
|
12
|
+
parser_type = @factory.load_parser
|
13
|
+
parser_type.should == :libxml
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should load LibXML if Nokogiri is not an available gem, but LibXML is" do
|
17
|
+
first_expectation = Gem.expects(:available?).with(/nokogiri/).returns(false)
|
18
|
+
second_expectation = @factory.expects(:require).with('libxml').returns(true)
|
19
|
+
parser_type = @factory.load_parser
|
20
|
+
first_expectation.satisfied?.should be_true
|
21
|
+
second_expectation.satisfied?.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not load Nokogiri if Nokogiri is not an available gem" do
|
25
|
+
expectation = @factory.expects(:require).with('nokogiri').returns(true).never()
|
26
|
+
parser_type = @factory.load_parser
|
27
|
+
expectation.satisfied?.should be_true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "no xml parsers are available" do
|
4
|
+
before(:each) do
|
5
|
+
Gem.stubs(:available?).returns(false)
|
6
|
+
@factory = Peachy::XmlParserFactory.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should blow up if no XML parsing library is available" do
|
10
|
+
lambda { @factory.load_parser }.should raise_error NoXmlParserAvailable
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "nokogiri is the available XML parser" do
|
4
|
+
before(:each) do
|
5
|
+
@factory = Peachy::XmlParserFactory.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should check whether Nokogiri is available" do
|
9
|
+
expectation = Gem.expects(:available?).with(/nokogiri/).returns(true)
|
10
|
+
parser_type = @factory.load_parser
|
11
|
+
expectation.satisfied?.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return Nokogiri if Nokogiri is an available gem" do
|
15
|
+
parser_type = @factory.load_parser
|
16
|
+
parser_type.should == :nokogiri
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should load Nokogiri if Nokogiri is an available gem" do
|
20
|
+
expectation = @factory.expects(:require).with('nokogiri').returns(true)
|
21
|
+
parser_type = @factory.load_parser
|
22
|
+
expectation.satisfied?.should be_true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -1,6 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
1
2
|
describe "interpreting element and attribute names that are defined in PascalCase" do
|
2
3
|
before(:each) do
|
3
|
-
@proxy = Peachy::Proxy.new
|
4
|
+
@proxy = Peachy::Proxy.new <<XML
|
5
|
+
<Root>
|
6
|
+
<TestNode>Check meh.</TestNode>
|
7
|
+
<SecondNode Id="2" RecordLabel="Wall of Sound">Check meh, too.</SecondNode>
|
8
|
+
<ThirdNode Id="2" RecordLabel="Wall of Sound"><Child>Check meh again.</Child></SecondNode>
|
9
|
+
</Root>
|
10
|
+
XML
|
4
11
|
end
|
5
12
|
|
6
13
|
it "should match a method to an element by pascal case" do
|
@@ -20,5 +27,15 @@ describe "interpreting element and attribute names that are defined in PascalCas
|
|
20
27
|
@proxy.root.second_node.record_label
|
21
28
|
@proxy.root.second_node.methods.should include 'record_label'
|
22
29
|
end
|
30
|
+
|
31
|
+
it "should define a method on a parent with attributes" do
|
32
|
+
@proxy.root.third_node.record_label.should == 'Wall of Sound'
|
33
|
+
@proxy.root.third_node.methods.should include 'record_label'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should allow child nodes to be selected after an attrbiute is selected on a parent node" do
|
37
|
+
@proxy.root.third_node.record_label.should == 'Wall of Sound'
|
38
|
+
@proxy.root.third_node.child.value.should == 'Check meh again.'
|
39
|
+
end
|
23
40
|
end
|
24
41
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "nokogiri wrapper" do
|
4
|
+
before(:each) do
|
5
|
+
@nokogiri_xml = Nokogiri::XML <<XML
|
6
|
+
<root identity="1234" category="awesomeness">
|
7
|
+
<child id="1">Hello</child>
|
8
|
+
<second_child attribute_one="one" attribute_two="two">Contents</second_child>
|
9
|
+
</root>
|
10
|
+
XML
|
11
|
+
@nokogiri = Peachy::Parsers::NokogiriWrapper.new @nokogiri_xml
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have all of the methods that I expect" do
|
15
|
+
@nokogiri.methods.should include 'content'
|
16
|
+
@nokogiri.methods.should include 'name'
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should return the expected content" do
|
20
|
+
@simple_noko = Peachy::Parsers::NokogiriWrapper.new(Nokogiri::XML('<xml>Hello</xml>'))
|
21
|
+
@simple_noko.content.should == 'Hello'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return the expected name" do
|
25
|
+
@nokogiri.name.should == 'document'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- NJ Pearman
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-05-
|
17
|
+
date: 2010-05-18 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -44,32 +44,40 @@ extensions: []
|
|
44
44
|
extra_rdoc_files:
|
45
45
|
- README.rdoc
|
46
46
|
files:
|
47
|
+
- lib/peachy/xml_node.rb
|
47
48
|
- lib/peachy/convention_checks.rb
|
48
49
|
- lib/peachy/childless_proxy_with_attributes.rb
|
49
50
|
- lib/peachy/method_name.rb
|
51
|
+
- lib/peachy/xml_parser_factory.rb
|
50
52
|
- lib/peachy/method_mask.rb
|
53
|
+
- lib/peachy/proxy_factory.rb
|
51
54
|
- lib/peachy/simple_content.rb
|
52
55
|
- lib/peachy/version.rb
|
53
56
|
- lib/peachy/proxy.rb
|
57
|
+
- lib/peachy/parsers/nokogiri_wrapper.rb
|
54
58
|
- lib/peachy/morph_into_array.rb
|
55
59
|
- lib/peachy/my_meta_class.rb
|
56
60
|
- lib/peachy/string_styler.rb
|
57
|
-
- lib/peachy/node_child_matcher.rb
|
58
61
|
- lib/no_matching_xml_part.rb
|
62
|
+
- lib/no_xml_parser_available.rb
|
59
63
|
- lib/invalid_proxy_parameters.rb
|
60
64
|
- lib/method_not_in_ruby_convention.rb
|
61
65
|
- lib/already_an_only_child.rb
|
62
66
|
- lib/peachy.rb
|
67
|
+
- spec/nokogiri_is_the_available_xml_parser_spec.rb
|
63
68
|
- spec/hyphen_separated_names_spec.rb
|
64
69
|
- spec/elements_referenced_as_collections_spec.rb
|
70
|
+
- spec/peachy_parsers_nokogiri_spec.rb
|
65
71
|
- spec/simple_content_wrapper_for_Peachy_spec.rb
|
66
72
|
- spec/collections_with_children_as_arrays_spec.rb
|
67
73
|
- spec/method_name_spec.rb
|
68
74
|
- spec/childless_elements_referenced_as_collections_spec.rb
|
69
75
|
- spec/simple_xml_collections_as_arrays_spec.rb
|
70
76
|
- spec/simple_element_referenced_as_collections_spec.rb
|
77
|
+
- spec/no_xml_parsers_are_available_spec.rb
|
71
78
|
- spec/using_peachy_proxy_incorrectly_spec.rb
|
72
79
|
- spec/inferring_a_method_from_an_attribute_spec.rb
|
80
|
+
- spec/libxml_is_the_available_xml_parser_spec.rb
|
73
81
|
- spec/camel_case_names_spec.rb
|
74
82
|
- spec/attributes_on_a_parent_node_spec.rb
|
75
83
|
- spec/pascal_case_names_spec.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Peachy
|
2
|
-
module NodeChildMatcher
|
3
|
-
# Runs the XPath for the method name against the underlying XML DOM,
|
4
|
-
# returning nil if no element or attribute matching the method name is found
|
5
|
-
# in the children of the current location in the DOM.
|
6
|
-
def find_matches method_name, node #=nokogiri_node
|
7
|
-
matches = node.xpath(xpath_for(method_name))
|
8
|
-
return nil if matches.length < 1
|
9
|
-
return matches
|
10
|
-
end
|
11
|
-
|
12
|
-
def find_match_by_attributes method_name, node
|
13
|
-
mapped = method_name.variations.map {|variation| node.attribute variation }
|
14
|
-
mapped.find {|match| match != nil }
|
15
|
-
end
|
16
|
-
|
17
|
-
# Gets the XPath for all variations of the MethodName instance
|
18
|
-
def xpath_for method_name
|
19
|
-
method_name.variations.map {|variation| "./#{variation}" } * '|'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|