peachy 0.3.3 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|