peachy 0.3.2 → 0.3.3
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/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
|