peachy 0.3.3 → 0.3.4
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/README.rdoc +18 -12
- data/lib/peachy.rb +24 -0
- data/lib/peachy/method_mask.rb +6 -2
- data/lib/peachy/method_name.rb +1 -3
- data/lib/peachy/morph_into_array.rb +3 -3
- data/lib/peachy/proxy.rb +6 -7
- data/lib/peachy/simple_content.rb +6 -4
- data/lib/peachy/version.rb +1 -1
- data/spec/elements_referenced_as_collections_spec.rb +10 -2
- data/spec/make_peachy_quiet_spec.rb +26 -0
- metadata +4 -3
data/README.rdoc
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
= Peachy
|
2
2
|
|
3
|
-
Peachy dynamically slurps XML from an underlying XML DOM, creating
|
3
|
+
Peachy dynamically slurps XML from an underlying XML DOM, creating Ruby methods
|
4
4
|
on the fly to match the elements and attributes of the XML.
|
5
5
|
|
6
6
|
Source available at http://github.com/njpearman/Peachy
|
7
7
|
|
8
8
|
== Install
|
9
|
-
The Peachy
|
9
|
+
The Peachy gem is available as you would expect. Run:
|
10
10
|
|
11
11
|
gem install peachy
|
12
12
|
|
@@ -32,7 +32,7 @@ Call #value on a childless node to get the contents of the node, such as the
|
|
32
32
|
example above.
|
33
33
|
|
34
34
|
Peachy expects method names to be called in the Ruby convention of lowercase with
|
35
|
-
underscores. It will do
|
35
|
+
underscores. It will do its best to match method names to elements and attributes
|
36
36
|
following different conventions (currently, this is camelCaseNames, PascalCaseNames
|
37
37
|
or hyphen-separated-names)
|
38
38
|
|
@@ -42,8 +42,8 @@ More detailed usage examples can be found in the .rb files in the /test director
|
|
42
42
|
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
|
-
puts 'XML: ' + proxy.xml.node
|
46
|
-
=> <node>Peachy</node>
|
45
|
+
puts 'XML: ' + proxy.xml.node.to_s
|
46
|
+
=> XML: <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.
|
@@ -51,14 +51,18 @@ is being used, but the XML will be valid and correct.
|
|
51
51
|
=== XML parsing
|
52
52
|
Peachy tries to determine which XML parser to load when it is first used. Nokogiri
|
53
53
|
is currently the first choice, defaulting to REXML if Nokogiri is not available.
|
54
|
-
|
55
|
-
|
54
|
+
Peachy requires the appropriate XML parser gem at runtime and, as such, I haven't
|
55
|
+
included Nokogiri as a dependency in the gemspec. It will use Nokogiri when it's
|
56
|
+
available; otherwise REXML will be loaded and used at runtime.
|
57
|
+
|
58
|
+
It is possible to extend out the parser support, for example Hpricot or LibXML,
|
59
|
+
so let me know if there are any other XML parsers that you'd like Peachy to support.
|
56
60
|
|
57
61
|
=== Elements and Attributes
|
58
62
|
Currently, elements and attributes are accessed in almost exactly the same way;
|
59
63
|
call a method on your current node matching the attribute or element name that
|
60
|
-
is required next. Elements need to have
|
61
|
-
|
64
|
+
is required next. Elements need to have #value called on them to get the contents
|
65
|
+
of the element, however.
|
62
66
|
|
63
67
|
E.g.
|
64
68
|
|
@@ -72,6 +76,8 @@ Peachy is just for slurping XML, so this convention should make it easy to know
|
|
72
76
|
how to access the property that you're after, be they elements or attributes.
|
73
77
|
|
74
78
|
=== No method name match
|
75
|
-
Peachy
|
76
|
-
|
77
|
-
|
79
|
+
By default, Peachy will raise a NoMatchingXmlPart error if a method call does not
|
80
|
+
match a child node of the current location. It's possible to globally switch of
|
81
|
+
this behaviour and return nil when no child node is found. This might be
|
82
|
+
desirable if you cannot be certain of the XML that you are trying to interpret
|
83
|
+
until runtime.
|
data/lib/peachy.rb
CHANGED
@@ -23,10 +23,34 @@ require File.join(File.dirname(__FILE__), 'peachy/proxy')
|
|
23
23
|
require File.join(File.dirname(__FILE__), 'peachy/childless_proxy_with_attributes')
|
24
24
|
|
25
25
|
module Peachy
|
26
|
+
# Tells Peachy to quietly return nil when an xml node is not found, rather than
|
27
|
+
# throwing a NoMatchingXmlPart error. Use this setting when you want to have a
|
28
|
+
# conditional piece of logic with an XML node that may or may not exist.
|
29
|
+
def self.be_quiet
|
30
|
+
@quiet = true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Tells Peachy to be loud about XML nodes that don't exist, by raising a
|
34
|
+
# NoMatchingXmlPart error. Use this setting when you want to know about any
|
35
|
+
# XML nodes that unexpectedly don't exist. This is the default setting, rather
|
36
|
+
# than #be_quiet.
|
37
|
+
def self.be_loud
|
38
|
+
@quiet = false
|
39
|
+
end
|
40
|
+
|
41
|
+
# Indicates whether Peachy is being quiet, i.e. whether Peachy will return nil
|
42
|
+
# when an XML node is not found by a Peachy::Proxy
|
43
|
+
def self.being_quiet?
|
44
|
+
return @quiet
|
45
|
+
end
|
46
|
+
|
47
|
+
# Tells Peachy that it should be whiny, and print all of the steps that it knows
|
48
|
+
# to report to screen.
|
26
49
|
def self.whine
|
27
50
|
@whine = true
|
28
51
|
end
|
29
52
|
|
53
|
+
# Indactes whether Peachy will #whine when it runs or not.
|
30
54
|
def self.whiny?
|
31
55
|
return @whine
|
32
56
|
end
|
data/lib/peachy/method_mask.rb
CHANGED
@@ -2,9 +2,13 @@ module Peachy
|
|
2
2
|
module MethodMask
|
3
3
|
private
|
4
4
|
def hide_public_methods exceptions
|
5
|
-
|
6
|
-
|
5
|
+
formatted_exception = exceptions.map {|method_name| version_safe_method(method_name)}
|
6
|
+
methods_to_hide = public_instance_methods.map {|method| method unless formatted_exception.include? method }.compact
|
7
7
|
private *methods_to_hide
|
8
8
|
end
|
9
|
+
|
10
|
+
def version_safe_method(method_name)
|
11
|
+
/^1\.8/ === RUBY_VERSION ? method_name.to_s : method_name.to_s.to_sym
|
12
|
+
end
|
9
13
|
end
|
10
14
|
end
|
data/lib/peachy/method_name.rb
CHANGED
@@ -12,9 +12,7 @@ module Peachy
|
|
12
12
|
# The valid varations are the underlying method name, plus all variations
|
13
13
|
# provided by methods defined in the StringStyler module.
|
14
14
|
def variations
|
15
|
-
|
16
|
-
array << send(method)
|
17
|
-
end).uniq
|
15
|
+
variation_methods.inject([@method_name]) {|array, method| array << send(method)}.uniq
|
18
16
|
end
|
19
17
|
|
20
18
|
def as_xpath
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Peachy
|
2
2
|
module MorphIntoArray
|
3
3
|
private
|
4
|
-
def
|
5
|
-
return (
|
4
|
+
def used_as_array method_name, block_given, *args
|
5
|
+
return (block_given or args.size > 0) && array_can?(method_name)
|
6
6
|
end
|
7
7
|
|
8
8
|
def array_can? method_name
|
9
|
-
Array.instance_methods.include?(method_name.to_s)
|
9
|
+
Array.instance_methods.include?(method_name.to_s) && method_name != :type
|
10
10
|
end
|
11
11
|
|
12
12
|
def morph_into_array to_add_to_array, method_to_invoke, *args, &block
|
data/lib/peachy/proxy.rb
CHANGED
@@ -6,7 +6,7 @@ module Peachy
|
|
6
6
|
# This hides all public methods on the class except for 'methods', 'nil?'
|
7
7
|
# 'respond_to?', 'inspect' and 'instance_eval', which I've found are too
|
8
8
|
# useful / fundamental / dangerous to hide.
|
9
|
-
hide_public_methods ['methods', 'nil?', 'respond_to?', 'inspect', 'instance_eval']
|
9
|
+
hide_public_methods ['methods', 'nil?', 'respond_to?', 'inspect', 'instance_eval', 'kind_of?', 'send']
|
10
10
|
|
11
11
|
# Takes either a string containing XML or a Nokogiri::XML::Element as the
|
12
12
|
# single argument.
|
@@ -68,9 +68,7 @@ module Peachy
|
|
68
68
|
#
|
69
69
|
def method_missing method_name, *args, &block
|
70
70
|
# check whether an Array method is called with arguments or a block
|
71
|
-
if
|
72
|
-
return morph_into_array(clone, method_name, *args, &block)
|
73
|
-
end
|
71
|
+
return morph_into_array(clone, method_name, *args, &block) if used_as_array(method_name, block_given?, *args)
|
74
72
|
|
75
73
|
# standard method_missing for any other call with arguments or a block
|
76
74
|
super if args.any? or block_given?
|
@@ -79,11 +77,11 @@ module Peachy
|
|
79
77
|
child_proxy = generate_method_for_xml(MethodName.new(method_name))
|
80
78
|
|
81
79
|
if !child_proxy.nil?
|
82
|
-
# found a match, so
|
80
|
+
# found a match, so mark as only child
|
83
81
|
acts_as_only_child
|
84
82
|
child_proxy
|
85
83
|
elsif array_can?(method_name)
|
86
|
-
# morph into an array, as method is a
|
84
|
+
# morph into an array, as method is a length one array call
|
87
85
|
new_proxy = node.create_from_element
|
88
86
|
morph_into_array(new_proxy, method_name)
|
89
87
|
else
|
@@ -106,7 +104,8 @@ module Peachy
|
|
106
104
|
end
|
107
105
|
|
108
106
|
def no_matching_xml method_name
|
109
|
-
raise NoMatchingXmlPart.new(method_name, name)
|
107
|
+
raise NoMatchingXmlPart.new(method_name, name) unless Peachy.being_quiet?
|
108
|
+
return nil
|
110
109
|
end
|
111
110
|
end
|
112
111
|
end
|
@@ -14,11 +14,13 @@ module Peachy
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def method_missing method_name, *args, &block
|
17
|
-
if
|
18
|
-
new_content = SimpleContent.new(@xml)
|
19
|
-
return morph_into_array(new_content, method_name, *args, &block)
|
20
|
-
end
|
17
|
+
return morph_with_content(method_name, *args, &block) if used_as_array(method_name, block_given?, *args)
|
21
18
|
super
|
22
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def morph_with_content method_name, *args, &block
|
23
|
+
return morph_into_array(SimpleContent.new(@xml), method_name, *args, &block)
|
24
|
+
end
|
23
25
|
end
|
24
26
|
end
|
data/lib/peachy/version.rb
CHANGED
@@ -5,7 +5,7 @@ describe "an element referenced as the first part of a collection" do
|
|
5
5
|
xml = <<XML
|
6
6
|
<xml>
|
7
7
|
<list>
|
8
|
-
<item id="1">
|
8
|
+
<item id="1" type="thingy">
|
9
9
|
<child>one</child>
|
10
10
|
</item>
|
11
11
|
</list>
|
@@ -52,5 +52,13 @@ MSG
|
|
52
52
|
@proxy.xml.list.item.child
|
53
53
|
lambda { @proxy.xml.list.item[0] }.should raise_error(AlreadyAnOnlyChild, expected_message)
|
54
54
|
end
|
55
|
-
end
|
56
55
|
|
56
|
+
it "should not treat Array#type as an array reference" do
|
57
|
+
expected_message = <<MSG
|
58
|
+
The 'item' node has already been accessed as a single child, but you are now trying to use it as a collection.
|
59
|
+
Do not try to access Peachy::Proxies in a mixed manner in your implementation.
|
60
|
+
MSG
|
61
|
+
@proxy.xml.list.item.type
|
62
|
+
lambda { @proxy.xml.list.item[0] }.should raise_error(AlreadyAnOnlyChild, expected_message)
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Peacy can be quitened down when necessary' do
|
4
|
+
before(:each) do
|
5
|
+
@peachy_proxy = Peachy::Proxy.new '<xml />'
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:each) do
|
9
|
+
Peachy.be_loud
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should know when it should be quiet" do
|
13
|
+
Peachy.be_quiet
|
14
|
+
Peachy.being_quiet?.should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should know when to be loud" do
|
18
|
+
Peachy.be_loud
|
19
|
+
Peachy.being_quiet?.should be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not blow up when it's told to be quiet" do
|
23
|
+
Peachy.be_quiet
|
24
|
+
@peachy_proxy.not_a_method.should be_nil
|
25
|
+
end
|
26
|
+
end
|
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
|
+
- 4
|
9
|
+
version: 0.3.4
|
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-
|
17
|
+
date: 2010-09-08 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- spec/collections_with_children_as_arrays_spec.rb
|
63
63
|
- spec/method_name_spec.rb
|
64
64
|
- spec/childless_elements_referenced_as_collections_spec.rb
|
65
|
+
- spec/make_peachy_quiet_spec.rb
|
65
66
|
- spec/simple_xml_collections_as_arrays_spec.rb
|
66
67
|
- spec/simple_element_referenced_as_collections_spec.rb
|
67
68
|
- spec/using_peachy_proxy_incorrectly_spec.rb
|