peachy 0.3.3 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,12 @@
1
1
  = Peachy
2
2
 
3
- Peachy dynamically slurps XML from an underlying XML DOM, creating ruby methods
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 Ruby gem is available as you would expect. Run:
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 it's best to match method names to elements and attributes
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
- It's possible to extend this out so let me know if there are any other XML parsers
55
- that you'd like Peachy to support.
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 .value or .to_s called on them to get
61
- the contents of the element, however.
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 is currently short-tempered, in that if no element or attribute match is
76
- found when drilling down through proxies, a NoMatchingXmlPart error will be
77
- raised.
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.
@@ -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
@@ -2,9 +2,13 @@ module Peachy
2
2
  module MethodMask
3
3
  private
4
4
  def hide_public_methods exceptions
5
- methods_to_hide = public_instance_methods.clone
6
- exceptions.each {|stay_public| methods_to_hide.delete(stay_public) }
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
@@ -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
- (variation_methods.inject([@method_name]) do |array, method|
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 you_use_me_like_an_array method_name, block_given, *args
5
- return ((block_given or args.size > 0) and array_can?(method_name))
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
@@ -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 you_use_me_like_an_array(method_name, block_given?, *args)
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 flag as only child
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 zero-length array call
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 you_use_me_like_an_array(method_name, block_given?, *args)
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
@@ -1,3 +1,3 @@
1
1
  module Peachy
2
- VERSION = '0.3.3'
2
+ VERSION = '0.3.4'
3
3
  end
@@ -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
- - 3
9
- version: 0.3.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-06-05 00:00:00 +01:00
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