peachy 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/README.rdoc +4 -4
- data/lib/nothing_to_mimic.rb +8 -1
- data/lib/peachy.rb +1 -2
- data/lib/peachy/childless_proxy_with_attributes.rb +6 -2
- data/lib/peachy/current_method_call.rb +51 -0
- data/lib/peachy/method_name.rb +7 -9
- data/lib/peachy/mimic.rb +21 -3
- data/lib/peachy/morph_into_array.rb +3 -10
- data/lib/peachy/my_meta_class.rb +1 -1
- data/lib/peachy/parsers/nokogiri_wrapper.rb +4 -16
- data/lib/peachy/parsers/parser_factory.rb +24 -11
- data/lib/peachy/parsers/parser_wrapper.rb +23 -1
- data/lib/peachy/parsers/rexml_wrapper.rb +7 -14
- data/lib/peachy/proxy.rb +8 -40
- data/lib/peachy/version.rb +1 -1
- data/lib/peachy/xml_node.rb +9 -8
- data/spec/inferring_a_method_from_element_name_spec.rb +1 -0
- data/spec/mimc_spec.rb +1 -1
- data/spec/nokogiri_is_the_available_xml_parser_spec.rb +41 -33
- data/spec/only_rexml_is_available_spec.rb +11 -6
- data/spec/parsers/all_parser_wrappers_spec.rb +0 -8
- data/spec/parsers/nokigiri_wrapper_spec.rb +12 -10
- data/spec/spec_helper.rb +0 -1
- data/spec/using_peachy_proxy_incorrectly_spec.rb +2 -1
- metadata +4 -5
- data/lib/peachy/parsers/with_xpath.rb +0 -10
- data/lib/peachy/proxy_factory.rb +0 -23
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.3.3
|
2
|
+
* Minor improvements
|
3
|
+
* Added some more documentation to methods.
|
4
|
+
* Removed whiny-ness from specs.
|
5
|
+
* Improvements to structure of internals, introducing some new classes.
|
6
|
+
* Added some guard clauses on specs that are impacted when Nokogiri is not installed.
|
7
|
+
|
1
8
|
== 0.3.2
|
2
9
|
* Minor improvements
|
3
10
|
* Better support for Ruby 1.8.6
|
data/README.rdoc
CHANGED
@@ -26,10 +26,10 @@ Once you have a Proxy, it's straightforward to drill down through the XML by
|
|
26
26
|
node name:
|
27
27
|
|
28
28
|
puts 'Contents: ' + proxy.xml.node.value
|
29
|
-
|
29
|
+
=> Contents: Peachy
|
30
30
|
|
31
|
-
Call #value on a childless node to get the contents the node, such as the
|
32
|
-
above.
|
31
|
+
Call #value on a childless node to get the contents of the node, such as the
|
32
|
+
example above.
|
33
33
|
|
34
34
|
Peachy expects method names to be called in the Ruby convention of lowercase with
|
35
35
|
underscores. It will do it's best to match method names to elements and attributes
|
@@ -43,7 +43,7 @@ It's possible to call #to_s on any node in the tree to get the underlying XML at
|
|
43
43
|
that point in the tree, such as:
|
44
44
|
|
45
45
|
puts 'XML: ' + proxy.xml.node
|
46
|
-
|
46
|
+
=> <node>Peachy</node>
|
47
47
|
|
48
48
|
The exact representation of the XML will depend on the underlying XML parser that
|
49
49
|
is being used, but the XML will be valid and correct.
|
data/lib/nothing_to_mimic.rb
CHANGED
@@ -1,2 +1,9 @@
|
|
1
1
|
class NothingToMimic < Exception
|
2
|
-
|
2
|
+
def initialize
|
3
|
+
super <<MESSAGE
|
4
|
+
You aren't using Mimic correctly. Call Mimic.make_a_mimic_of(to_mimic, subject)
|
5
|
+
passing the object to mimic as to_mimic and the target of the mimic invocation as
|
6
|
+
subject. Shazaaam!
|
7
|
+
MESSAGE
|
8
|
+
end
|
9
|
+
end
|
data/lib/peachy.rb
CHANGED
@@ -12,15 +12,14 @@ require File.join(File.dirname(__FILE__), 'peachy/mimic')
|
|
12
12
|
require File.join(File.dirname(__FILE__), 'peachy/morph_into_array')
|
13
13
|
require File.join(File.dirname(__FILE__), 'peachy/my_meta_class')
|
14
14
|
require File.join(File.dirname(__FILE__), 'peachy/xml_node')
|
15
|
+
require File.join(File.dirname(__FILE__), 'peachy/current_method_call')
|
15
16
|
require File.join(File.dirname(__FILE__), 'peachy/simple_content')
|
16
17
|
require File.join(File.dirname(__FILE__), 'peachy/parsers/parser_factory')
|
17
|
-
require File.join(File.dirname(__FILE__), 'peachy/parsers/with_xpath')
|
18
18
|
require File.join(File.dirname(__FILE__), 'peachy/parsers/parser_wrapper')
|
19
19
|
require File.join(File.dirname(__FILE__), 'peachy/parsers/nokogiri_wrapper')
|
20
20
|
require File.join(File.dirname(__FILE__), 'peachy/parsers/rexml_wrapper')
|
21
21
|
require File.join(File.dirname(__FILE__), 'peachy/parsers/rexml_attribute_wrapper')
|
22
22
|
require File.join(File.dirname(__FILE__), 'peachy/proxy')
|
23
|
-
require File.join(File.dirname(__FILE__), 'peachy/proxy_factory')
|
24
23
|
require File.join(File.dirname(__FILE__), 'peachy/childless_proxy_with_attributes')
|
25
24
|
|
26
25
|
module Peachy
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Peachy
|
2
|
-
|
2
|
+
module ChildlessProxyWithAttributes
|
3
3
|
# Returns the text content of the XML node encapsulated by this instance.
|
4
4
|
def value
|
5
5
|
acts_as_only_child
|
@@ -7,9 +7,13 @@ module Peachy
|
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
|
+
# The implementation for Proxy#generate_method_for_xml is far more straightforward
|
11
|
+
# when the underlying element is a childless element that has attributes.
|
10
12
|
def generate_method_for_xml method_name
|
11
13
|
method_name.check_for_convention
|
12
|
-
|
14
|
+
CurrentMethodCall.new(self, method_name).create_method_for_attribute do |match|
|
15
|
+
no_matching_xml(method_name) if match.nil?
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Peachy
|
2
|
+
class CurrentMethodCall
|
3
|
+
extend MethodMask
|
4
|
+
include MyMetaClass, XmlNode
|
5
|
+
|
6
|
+
def initialize proxy, method
|
7
|
+
@method_name = method
|
8
|
+
@proxy = proxy
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_method_for_child_or_content matches
|
12
|
+
return define_child_array(matches) if matches.size > 1
|
13
|
+
child = matches[0].create_from_element
|
14
|
+
define_child_as(child)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_attribute
|
18
|
+
create_method_for_attribute if @proxy.node.has_children_and_attributes?
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_method_for_attribute
|
22
|
+
match = find_match_by_attributes
|
23
|
+
yield match if block_given?
|
24
|
+
define_child_as(match.content) unless match.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
[:find_matches, :find_match_by_attributes].each do |method|
|
28
|
+
define_method(method) { @proxy.node.send(method, @method_name) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def define_child_array matches
|
32
|
+
define_child(@method_name) { return CurrentMethodCall.matches_to_array(matches) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_child_as child
|
36
|
+
define_child(method_name) { return child }
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_child method_name, &block
|
40
|
+
@proxy.eval_on_singleton_class { define_method(method_name.to_sym, &block) }
|
41
|
+
yield
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
attr_reader :method_name
|
46
|
+
|
47
|
+
def self.matches_to_array matches
|
48
|
+
matches.inject([]) {|array, child| array << child.create_from_element }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/peachy/method_name.rb
CHANGED
@@ -2,6 +2,8 @@ module Peachy
|
|
2
2
|
class MethodName
|
3
3
|
include StringStyler
|
4
4
|
|
5
|
+
[:to_s, :to_sym].each {|method| define_method(method) { @method_name.send(method) }}
|
6
|
+
|
5
7
|
def initialize method_name
|
6
8
|
@method_name = method_name.to_s
|
7
9
|
end
|
@@ -15,6 +17,10 @@ module Peachy
|
|
15
17
|
end).uniq
|
16
18
|
end
|
17
19
|
|
20
|
+
def as_xpath
|
21
|
+
variations.map {|variation| "./#{variation}" } * '|'
|
22
|
+
end
|
23
|
+
|
18
24
|
# Checks whether the method name is in the accepted convention, raising a
|
19
25
|
# MethodNotInRubyConvention if it's not. This check does not allow method
|
20
26
|
# names to have question marks, exclamation marks or numbers, however.
|
@@ -22,14 +28,6 @@ module Peachy
|
|
22
28
|
raise MethodNotInRubyConvention.new(self) unless matches_convention?
|
23
29
|
end
|
24
30
|
|
25
|
-
def to_s
|
26
|
-
return @method_name
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_sym
|
30
|
-
return @method_name.to_sym
|
31
|
-
end
|
32
|
-
|
33
31
|
private
|
34
32
|
def variation_methods
|
35
33
|
Peachy::StringStyler.private_instance_methods
|
@@ -39,7 +37,7 @@ module Peachy
|
|
39
37
|
# underscores. This method does not allow question marks, excalmation marks
|
40
38
|
# or numbers, however.
|
41
39
|
def matches_convention?
|
42
|
-
|
40
|
+
@method_name =~ /^[a-z]+(?:_[a-z]+){0,}$/
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
data/lib/peachy/mimic.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
module Peachy
|
2
2
|
module Mimic
|
3
|
-
|
3
|
+
# Use this method to make a mimic of an object. The first argument passed is
|
4
|
+
# the object to be mimicked and the second is the subject of the mimic action.
|
5
|
+
# All previous methods defined on the subject will be buried.
|
6
|
+
def self.make_a_mimic_of to_mimic, subject
|
7
|
+
subject.instance_eval do
|
8
|
+
(class << self; self; end).class_eval do
|
9
|
+
define_method(:subject) { to_mimic }
|
10
|
+
include Mimic
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# This method has been defined as a template. If you just include Mimic as
|
16
|
+
# a module on your class you will get a NothingToMimic error when calling #mimic.
|
17
|
+
#
|
18
|
+
# Use Mimic#make_a_mimic_of to turn an object into a mimic.
|
19
|
+
def subject
|
4
20
|
raise NothingToMimic.new
|
5
21
|
end
|
6
|
-
|
22
|
+
|
23
|
+
# Delegates the method_missing call to the underlying object that is being
|
24
|
+
# mimicked.
|
7
25
|
def method_missing method_name, *args, &block
|
8
|
-
|
26
|
+
subject.send(method_name, *args, &block)
|
9
27
|
end
|
10
28
|
end
|
11
29
|
end
|
@@ -9,18 +9,11 @@ module Peachy
|
|
9
9
|
Array.instance_methods.include?(method_name.to_s)
|
10
10
|
end
|
11
11
|
|
12
|
-
def mimic object_to_mimic
|
13
|
-
eval_on_singleton_class do
|
14
|
-
define_method(:mimic) { object_to_mimic }
|
15
|
-
include Mimic
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
12
|
def morph_into_array to_add_to_array, method_to_invoke, *args, &block
|
20
13
|
puts "[Peachy::Proxy] Currently acts as #{@acts_as}" if Peachy.whiny?
|
21
|
-
raise AlreadyAnOnlyChild.new(name) if is_an_only_child
|
14
|
+
raise AlreadyAnOnlyChild.new(name) if is_an_only_child?
|
22
15
|
puts "[Peachy::Proxy] So #{name} should be an Array, then." if Peachy.whiny?
|
23
|
-
|
16
|
+
Mimic.make_a_mimic_of [to_add_to_array], self
|
24
17
|
return send(method_to_invoke, *args, &block)
|
25
18
|
end
|
26
19
|
|
@@ -28,7 +21,7 @@ module Peachy
|
|
28
21
|
@acts_as = :only_child
|
29
22
|
end
|
30
23
|
|
31
|
-
def is_an_only_child
|
24
|
+
def is_an_only_child?
|
32
25
|
@acts_as == :only_child
|
33
26
|
end
|
34
27
|
end
|
data/lib/peachy/my_meta_class.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
module Peachy
|
2
2
|
module Parsers
|
3
3
|
class NokogiriWrapper < ParserWrapper
|
4
|
-
|
5
|
-
|
4
|
+
[:content, :name, :to_s].each{|method| define_method(method){ @nokogiri.send(method) }}
|
5
|
+
|
6
6
|
def initialize nokogiri
|
7
7
|
@nokogiri = nokogiri
|
8
8
|
end
|
@@ -11,7 +11,7 @@ module Peachy
|
|
11
11
|
# returning nil if no element or attribute matching the method name is found
|
12
12
|
# in the children of the current location in the DOM.
|
13
13
|
def find_matches method_name
|
14
|
-
matches = xpath(
|
14
|
+
matches = xpath(method_name.as_xpath)
|
15
15
|
matches.any? ? matches : nil
|
16
16
|
end
|
17
17
|
|
@@ -26,6 +26,7 @@ module Peachy
|
|
26
26
|
has_children? and has_attributes?
|
27
27
|
end
|
28
28
|
|
29
|
+
private
|
29
30
|
# Determines whether the given element contains any child elements or not.
|
30
31
|
# The choice of implementation is based on performance tests between using
|
31
32
|
# XPath and a Ruby iterator.
|
@@ -37,19 +38,6 @@ module Peachy
|
|
37
38
|
@nokogiri.attribute_nodes.size > 0
|
38
39
|
end
|
39
40
|
|
40
|
-
def content
|
41
|
-
@nokogiri.content
|
42
|
-
end
|
43
|
-
|
44
|
-
def name
|
45
|
-
@nokogiri.name
|
46
|
-
end
|
47
|
-
|
48
|
-
def to_s
|
49
|
-
@nokogiri.to_s
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
41
|
def xpath xpath
|
54
42
|
@nokogiri.xpath(xpath).map{|noko_node| make_from(noko_node) }
|
55
43
|
end
|
@@ -1,22 +1,35 @@
|
|
1
1
|
module Peachy
|
2
2
|
module Parsers
|
3
3
|
class ParserFactory
|
4
|
+
# Loads the first available XML parser defined in the list of parsers that
|
5
|
+
# Peachy can use. This requires the Gem for the parser and creates the method
|
6
|
+
# make_from, which will return a new instance of the ParserWrapper for that
|
7
|
+
# library.
|
8
|
+
# In order of preference, the Gems that Peachy can currently use for parsing
|
9
|
+
# XML are:
|
10
|
+
# * Nokogiri
|
11
|
+
# * REXML
|
4
12
|
def load_parser
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
def make_from raw_xml
|
11
|
-
return NokogiriWrapper.new(Nokogiri::XML(raw_xml)) if @parser == :nokogiri
|
12
|
-
return REXMLWrapper.new(REXML::Document.new(raw_xml)) if @parser == :rexml
|
13
|
+
preferred_parser = Parsers.find {|parser| Gem.available? parser[:gem] }
|
14
|
+
preferred_parser = DefaultParser if preferred_parser.nil?
|
15
|
+
puts "Loading #{preferred_parser[:gem]} as the XML parser to use" if Peachy.whiny?
|
16
|
+
set_the_parser preferred_parser
|
13
17
|
end
|
14
18
|
|
15
19
|
private
|
16
|
-
def
|
17
|
-
|
18
|
-
|
20
|
+
def set_the_parser preferred_parser
|
21
|
+
self.class.class_eval { define_method(:make_from, preferred_parser[:implementation]) }
|
22
|
+
require(preferred_parser[:gem])
|
19
23
|
end
|
24
|
+
|
25
|
+
Parsers =
|
26
|
+
[{:gem => 'nokogiri', :implementation => lambda {|xml| NokogiriWrapper.new(Nokogiri::XML(xml)) }}]
|
27
|
+
|
28
|
+
DefaultParser =
|
29
|
+
{
|
30
|
+
:gem => 'rexml/document',
|
31
|
+
:implementation => lambda {|xml| REXMLWrapper.new(REXML::Document.new(xml)) }
|
32
|
+
}
|
20
33
|
end
|
21
34
|
end
|
22
35
|
end
|
@@ -1,7 +1,29 @@
|
|
1
1
|
module Peachy
|
2
2
|
module Parsers
|
3
3
|
class ParserWrapper
|
4
|
-
def
|
4
|
+
def create_from_element
|
5
|
+
return create_proxy if has_children?
|
6
|
+
return create_proxy_with_attributes if has_attributes?
|
7
|
+
return create_content_child
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
def create_content_child
|
12
|
+
SimpleContent.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_proxy
|
16
|
+
Proxy.new(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_proxy_with_attributes
|
20
|
+
childless_proxy_with_attributes = Proxy.new(self)
|
21
|
+
childless_proxy_with_attributes.instance_eval do
|
22
|
+
(class << self; self; end).instance_eval do
|
23
|
+
include ChildlessProxyWithAttributes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
return childless_proxy_with_attributes
|
5
27
|
end
|
6
28
|
end
|
7
29
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Peachy
|
2
2
|
module Parsers
|
3
3
|
class REXMLWrapper < ParserWrapper
|
4
|
-
|
4
|
+
[:name, :to_s].each{|method| define_method(method) { @rexml.send(method) }}
|
5
5
|
|
6
6
|
def initialize rexml_element
|
7
7
|
@rexml = rexml_element
|
8
8
|
end
|
9
9
|
|
10
10
|
def find_matches method_name
|
11
|
-
matches = REXML::XPath.match(@rexml,
|
11
|
+
matches = REXML::XPath.match(@rexml, method_name.as_xpath)
|
12
12
|
return nil if matches.size < 1
|
13
13
|
matches.map {|node| REXMLWrapper.new(node)}
|
14
14
|
end
|
@@ -18,14 +18,6 @@ module Peachy
|
|
18
18
|
match.nil? ? nil : REXMLAttributeWrapper.new(match)
|
19
19
|
end
|
20
20
|
|
21
|
-
def has_children?
|
22
|
-
@rexml.elements.size > 0
|
23
|
-
end
|
24
|
-
|
25
|
-
def has_attributes?
|
26
|
-
@rexml.attributes.size > 0
|
27
|
-
end
|
28
|
-
|
29
21
|
def has_children_and_attributes?
|
30
22
|
has_children? and has_attributes?
|
31
23
|
end
|
@@ -34,12 +26,13 @@ module Peachy
|
|
34
26
|
@rexml.text
|
35
27
|
end
|
36
28
|
|
37
|
-
|
38
|
-
|
29
|
+
private
|
30
|
+
def has_children?
|
31
|
+
@rexml.elements.size > 0
|
39
32
|
end
|
40
33
|
|
41
|
-
def
|
42
|
-
@rexml.
|
34
|
+
def has_attributes?
|
35
|
+
@rexml.attributes.size > 0
|
43
36
|
end
|
44
37
|
end
|
45
38
|
end
|
data/lib/peachy/proxy.rb
CHANGED
@@ -4,9 +4,9 @@ module Peachy
|
|
4
4
|
include MorphIntoArray, MyMetaClass, XmlNode
|
5
5
|
|
6
6
|
# This hides all public methods on the class except for 'methods', 'nil?'
|
7
|
-
# 'respond_to?' and '
|
8
|
-
#
|
9
|
-
hide_public_methods ['methods', 'nil?', 'respond_to?', 'inspect']
|
7
|
+
# 'respond_to?', 'inspect' and 'instance_eval', which I've found are too
|
8
|
+
# useful / fundamental / dangerous to hide.
|
9
|
+
hide_public_methods ['methods', 'nil?', 'respond_to?', 'inspect', 'instance_eval']
|
10
10
|
|
11
11
|
# Takes either a string containing XML or a Nokogiri::XML::Element as the
|
12
12
|
# single argument.
|
@@ -84,7 +84,7 @@ module Peachy
|
|
84
84
|
child_proxy
|
85
85
|
elsif array_can?(method_name)
|
86
86
|
# morph into an array, as method is a zero-length array call
|
87
|
-
new_proxy =
|
87
|
+
new_proxy = node.create_from_element
|
88
88
|
morph_into_array(new_proxy, method_name)
|
89
89
|
else
|
90
90
|
no_matching_xml(method_name)
|
@@ -94,45 +94,13 @@ module Peachy
|
|
94
94
|
private
|
95
95
|
def generate_method_for_xml method_name
|
96
96
|
method_name.check_for_convention
|
97
|
-
|
97
|
+
current_call = CurrentMethodCall.new(self, method_name)
|
98
|
+
attribute_content = current_call.create_attribute
|
98
99
|
return attribute_content unless attribute_content.nil?
|
99
|
-
matches =
|
100
|
-
matches.nil? ? nil : create_method_for_child_or_content(
|
100
|
+
matches = current_call.find_matches
|
101
|
+
matches.nil? ? nil : current_call.create_method_for_child_or_content(matches)
|
101
102
|
end
|
102
103
|
|
103
|
-
def create_method_for_child_or_content method_name, matches
|
104
|
-
return create_from_element_list(method_name, matches) if matches.size > 1
|
105
|
-
child = ProxyFactory.create_from_element(matches[0])
|
106
|
-
define_child(method_name, child)
|
107
|
-
end
|
108
|
-
|
109
|
-
def create_attribute method_name
|
110
|
-
create_method_for_attribute(method_name) if node.has_children_and_attributes?
|
111
|
-
end
|
112
|
-
|
113
|
-
def create_method_for_attribute method_name
|
114
|
-
match = node.find_match_by_attributes(method_name)
|
115
|
-
yield match if block_given?
|
116
|
-
define_child(method_name, match.content) unless match.nil?
|
117
|
-
end
|
118
|
-
|
119
|
-
def create_from_element_list method_name, matches
|
120
|
-
define_method(method_name) { return matches_to_array(matches) }
|
121
|
-
end
|
122
|
-
|
123
|
-
def matches_to_array matches
|
124
|
-
matches.inject([]) {|array, child| array << ProxyFactory.create_from_element(child) }
|
125
|
-
end
|
126
|
-
|
127
|
-
def define_child method_name, child
|
128
|
-
define_method(method_name) { return child }
|
129
|
-
end
|
130
|
-
|
131
|
-
def define_method method_name, &block
|
132
|
-
eval_on_singleton_class { define_method(method_name.to_sym, &block) }
|
133
|
-
yield
|
134
|
-
end
|
135
|
-
|
136
104
|
def variables_are_nil?
|
137
105
|
@xml.nil? and @node.nil?
|
138
106
|
end
|
data/lib/peachy/version.rb
CHANGED
data/lib/peachy/xml_node.rb
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
module Peachy
|
2
2
|
module XmlNode
|
3
|
+
protected
|
4
|
+
# The encapsulated Nokogiri node, which is lazy loaded from the @xml instance
|
5
|
+
# variable.
|
6
|
+
def node
|
7
|
+
raise InvalidProxyParameters.new(:xml => nil, :nokogiri => nil) if variables_are_nil?
|
8
|
+
@node ||= create
|
9
|
+
end
|
10
|
+
|
3
11
|
private
|
4
12
|
def clone
|
5
|
-
|
13
|
+
node.create_from_element
|
6
14
|
end
|
7
15
|
|
8
16
|
# Returns the name of the encapsulated node.
|
@@ -10,13 +18,6 @@ module Peachy
|
|
10
18
|
node.name
|
11
19
|
end
|
12
20
|
|
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
|
-
@node ||= create
|
18
|
-
end
|
19
|
-
|
20
21
|
def create
|
21
22
|
load_factory unless defined? @factory
|
22
23
|
@factory.make_from @xml
|
@@ -46,6 +46,7 @@ describe "inferring a method from an element name" do
|
|
46
46
|
@proxy.methods.should include('nil?')
|
47
47
|
@proxy.methods.should include('respond_to?')
|
48
48
|
@proxy.methods.should include('to_s')
|
49
|
+
@proxy.methods.should include('instance_eval')
|
49
50
|
@proxy.methods.should_not include('id')
|
50
51
|
end
|
51
52
|
end
|
data/spec/mimc_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe "using a Mimic" do
|
|
15
15
|
it "should call the underlying object" do
|
16
16
|
to_mimic = "Hello"
|
17
17
|
@mimic.instance_eval do
|
18
|
-
(class << self; self; end).instance_eval { define_method(:
|
18
|
+
(class << self; self; end).instance_eval { define_method(:subject) { to_mimic } }
|
19
19
|
end
|
20
20
|
|
21
21
|
@mimic.chomp('o').should == "Hell"
|
@@ -1,40 +1,48 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'nokogiri'
|
3
2
|
|
4
|
-
describe "nokogiri is the available XML parser" do
|
5
|
-
before(:each) do
|
6
|
-
@factory = Peachy::Parsers::ParserFactory.new
|
7
|
-
expectation = @factory.stubs(:require).with('nokogiri').returns(true)
|
8
|
-
end
|
9
3
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
expectation.satisfied?.should be_true
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should return Nokogiri" do
|
17
|
-
parser_type = @factory.load_parser
|
18
|
-
parser_type.should == :nokogiri
|
19
|
-
end
|
4
|
+
# this is to ignore this spec if the nokogiri gem is not available
|
5
|
+
if Gem.available? 'nokogiri'
|
6
|
+
require 'nokogiri'
|
20
7
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
8
|
+
describe "nokogiri is the available XML parser" do
|
9
|
+
before(:each) do
|
10
|
+
@factory = Peachy::Parsers::ParserFactory.new
|
11
|
+
expectation = @factory.stubs(:require).with('nokogiri').returns(true)
|
12
|
+
end
|
26
13
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
expectation.satisfied?.should be_true
|
31
|
-
end
|
14
|
+
it "should indicate that the parser has been loaded" do
|
15
|
+
@factory.load_parser.should be_true
|
16
|
+
end
|
32
17
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
18
|
+
it "should check whether Nokogiri is available" do
|
19
|
+
expectation = Gem.expects(:available?).with('nokogiri').returns(true)
|
20
|
+
parser_type = @factory.load_parser
|
21
|
+
expectation.satisfied?.should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should load Nokogiri" do
|
25
|
+
expectation = @factory.expects(:require).with('nokogiri').returns(true)
|
26
|
+
parser_type = @factory.load_parser
|
27
|
+
expectation.satisfied?.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not load REXML" do
|
31
|
+
expectation = @factory.expects(:require).with('rexml/document').never.returns(true)
|
32
|
+
parser_type = @factory.load_parser
|
33
|
+
expectation.satisfied?.should be_true
|
34
|
+
end
|
40
35
|
|
36
|
+
it "should enable a way to a new NokogiriWrapper" do
|
37
|
+
@factory.load_parser
|
38
|
+
@factory.methods.should include('make_from')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should create a NokogiriWrapper from xml" do
|
42
|
+
@factory.load_parser
|
43
|
+
wrapper = @factory.make_from '<thing>Stuff</thing>'
|
44
|
+
wrapper.should be_a(Peachy::Parsers::NokogiriWrapper)
|
45
|
+
wrapper.content.should == 'Stuff'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -5,12 +5,12 @@ describe "only REXML is available" do
|
|
5
5
|
before(:each) do
|
6
6
|
@factory = Peachy::Parsers::ParserFactory.new
|
7
7
|
@factory.stubs(:require).with('rexml/document').returns(true)
|
8
|
-
Gem.stubs(:available?).with(
|
8
|
+
Gem.stubs(:available?).with('nokogiri').returns(false)
|
9
|
+
Gem.stubs(:available?).with('rexml/document').returns(true)
|
9
10
|
end
|
10
11
|
|
11
|
-
it "should
|
12
|
-
|
13
|
-
parser.should == :rexml
|
12
|
+
it "should indicate that the parser has been loaded" do
|
13
|
+
@factory.load_parser.should be_true
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should load REXML" do
|
@@ -20,7 +20,7 @@ describe "only REXML is available" do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should check whether other XML parsers are available" do
|
23
|
-
expectation = Gem.expects(:available?).with(
|
23
|
+
expectation = Gem.expects(:available?).with('nokogiri').returns(false)
|
24
24
|
@factory.load_parser
|
25
25
|
expectation.satisfied?.should be_true
|
26
26
|
end
|
@@ -31,11 +31,16 @@ describe "only REXML is available" do
|
|
31
31
|
expectation.satisfied?.should be_true
|
32
32
|
end
|
33
33
|
|
34
|
+
it "should enable a way to a new REXMLWrapper" do
|
35
|
+
@factory.load_parser
|
36
|
+
@factory.methods.should include('make_from')
|
37
|
+
end
|
38
|
+
|
34
39
|
it "should create a REXMLWrapper from xml" do
|
35
40
|
@factory.load_parser
|
36
41
|
wrapper = @factory.make_from '<thing>Stuff</thing>'
|
37
42
|
wrapper.should be_a(Peachy::Parsers::REXMLWrapper)
|
38
|
-
wrapper.
|
43
|
+
wrapper.name.should == ''
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
@@ -25,14 +25,6 @@ shared_examples_for "all parser wrappers" do
|
|
25
25
|
matches.should be_nil
|
26
26
|
end
|
27
27
|
|
28
|
-
it "should indicate that an element has children" do
|
29
|
-
@wrapper.has_children?.should be_true
|
30
|
-
end
|
31
|
-
|
32
|
-
it "should indicate that an element has an attributes" do
|
33
|
-
@wrapper.has_attributes?.should be_true
|
34
|
-
end
|
35
|
-
|
36
28
|
it "should indicate that an element has both children and an attribute" do
|
37
29
|
@wrapper.has_children_and_attributes?.should be_true
|
38
30
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'nokogiri'
|
3
2
|
require File.join(File.dirname(__FILE__), 'all_parser_wrappers_spec')
|
4
3
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
# this is to ignore this spec if the nokogiri gem is not available
|
5
|
+
if Gem.available? 'nokogiri'
|
6
|
+
require 'nokogiri'
|
7
|
+
describe "a Peachy::Parsers::NokogiriWrapper" do
|
8
|
+
before(:each) do
|
9
|
+
@raw_xml = "<root type=\"test\">\n <child>Name</child>\n</root>"
|
10
|
+
noko = Nokogiri::XML(@raw_xml)
|
11
|
+
@wrapper = Peachy::Parsers::NokogiriWrapper.new((noko/'root')[0])
|
12
|
+
@expected_wrapper_class = Peachy::Parsers::NokogiriWrapper
|
13
|
+
end
|
12
14
|
|
13
|
-
|
15
|
+
it_should_behave_like "all parser wrappers"
|
16
|
+
end
|
14
17
|
end
|
15
|
-
|
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,8 @@ describe "using Peachy::Proxy incorrectly" do
|
|
4
4
|
end
|
5
5
|
|
6
6
|
it 'should raise a well written error if the method does not map to anything in the underlying XML node' do
|
7
|
-
|
7
|
+
root_name = Gem.available?('nokogiri') ? 'document' : ''
|
8
|
+
lambda { @proxy.missing }.should raise_error(NoMatchingXmlPart, "missing is not contained as a child of the node #{root_name}.")
|
8
9
|
end
|
9
10
|
|
10
11
|
it "should raise an error if the method name is not in Ruby convention" do
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 3
|
9
|
+
version: 0.3.3
|
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-06-05 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -36,14 +36,13 @@ files:
|
|
36
36
|
- lib/peachy/method_name.rb
|
37
37
|
- lib/peachy/mimic.rb
|
38
38
|
- lib/peachy/method_mask.rb
|
39
|
-
- lib/peachy/proxy_factory.rb
|
40
39
|
- lib/peachy/simple_content.rb
|
40
|
+
- lib/peachy/current_method_call.rb
|
41
41
|
- lib/peachy/version.rb
|
42
42
|
- lib/peachy/proxy.rb
|
43
43
|
- lib/peachy/parsers/rexml_attribute_wrapper.rb
|
44
44
|
- lib/peachy/parsers/nokogiri_wrapper.rb
|
45
45
|
- lib/peachy/parsers/parser_factory.rb
|
46
|
-
- lib/peachy/parsers/with_xpath.rb
|
47
46
|
- lib/peachy/parsers/parser_wrapper.rb
|
48
47
|
- lib/peachy/parsers/rexml_wrapper.rb
|
49
48
|
- lib/peachy/morph_into_array.rb
|
data/lib/peachy/proxy_factory.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Peachy
|
2
|
-
class ProxyFactory
|
3
|
-
class << self
|
4
|
-
def create_from_element match
|
5
|
-
return create_proxy(match) if match.has_children?
|
6
|
-
return create_proxy_with_attributes(match) if match.has_attributes?
|
7
|
-
return create_content_child(match)
|
8
|
-
end
|
9
|
-
|
10
|
-
def create_content_child match
|
11
|
-
SimpleContent.new(match)
|
12
|
-
end
|
13
|
-
|
14
|
-
def create_proxy match
|
15
|
-
Proxy.new(match)
|
16
|
-
end
|
17
|
-
|
18
|
-
def create_proxy_with_attributes match
|
19
|
-
ChildlessProxyWithAttributes.new(match)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|