xml_dsl 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8039a8956aa2ed81f448ceb371bf92523f9f1a3c
4
- data.tar.gz: 5d8486f335d6a3fc412ce09ebe312a6738b187fe
3
+ metadata.gz: a06859b2ea2ebab29cd30ca0dd451005459ed911
4
+ data.tar.gz: 476df9143b24ecc659d2751d06d4b315216394c5
5
5
  SHA512:
6
- metadata.gz: f24e74b53fb2e66b325c032c749ff1795a6268fbc79f1ad2cb9a0c0c392266d774027ab0cb6d5a4b86951813b52d3f6cc8ea87720b57714dd29f4cf7787178e0
7
- data.tar.gz: 3981133746da9191c4b25555f65915257a3204772204a1289efb52e77e10e2f96d075b1e264a3d1721ced396bae67cd0c754e9c64fd041a97872e99fbdf69dc3
6
+ metadata.gz: 8803eeda3e875094fb8a52fed5bf224b5fd0b9f3eebf94f7c6f9632fa8d5be086871bc3e14a05872c0d19795ca6c804662cc98fde2f79fd75554c3db86384343
7
+ data.tar.gz: 20d55686eebf557caefd68da858ffd8215c1105ae8d53d9231d0d48309402a6cdb469313d58010f047b13d6667a7c28802ab485844b33f26c228a66316667950
data/README.md CHANGED
@@ -70,6 +70,16 @@ Then we can define our mapper as following
70
70
  # any length of root path can be provided
71
71
  define_xml_parser Hash, :root, :offer do
72
72
 
73
+ # Here is basic validation blocks
74
+ # They MUST return some bool (if block)
75
+ before_parse? do |node|
76
+ !node.search('magick').empty?
77
+ end
78
+
79
+ # Or just check for must_have key (or path to it)
80
+ before_parse? :jim
81
+ before_parse? [:areas, 'area[type=hobby]']
82
+
73
83
  # We can define a block to call every time an XmlDsl::ParseError os raised
74
84
  # it is raised if null: true is passed to field declaration, or manually via raise XmlDsl::ParseError
75
85
  error_handle do |e, node|
@@ -100,10 +110,28 @@ Then we can define our mapper as following
100
110
  0
101
111
  end
102
112
  end
113
+
114
+ # If something goes wrong - just raise XmlDsl::ParseError manually
115
+ field :fuu do |_, node|
116
+ raise XmlDsl::ParseError, 'FUUU' if node.search(:areas).length > 5
117
+ end
103
118
  end
104
119
  end
105
120
  ```
106
121
 
122
+ Then you can use your newly defined parser as you wish:
123
+ ```
124
+ parser = Parser.new(nifty_xml, some_logger_eg)
125
+
126
+ # just iterate with block
127
+ parser.iterate do |instance|
128
+ do_stuff_with_newly_mapped_instance_whatever(instance)
129
+ end
130
+
131
+ # or you can pass some accumulator for your instances to be put into
132
+ parser.iterate acc: []
133
+ ```
134
+
107
135
  ## Contributing
108
136
 
109
137
  Feel free to request for some features or fork - implement - pul request.
@@ -7,11 +7,11 @@ module XmlDsl
7
7
  @block = block if block_given?
8
8
  end
9
9
 
10
- def call(instance, node, parser)
10
+ def call(a, b = nil, c = nil)
11
11
  if block
12
- self.send method, *[instance, node, parser] + args, &block
12
+ self.send method, *[a, b, c].compact + args, &block
13
13
  else
14
- self.send method, *[instance, node, parser] + args
14
+ self.send method, *[a, b, c].compact + args
15
15
  end
16
16
  end
17
17
 
@@ -21,15 +21,7 @@ module XmlDsl
21
21
  instance[target] = parser.instance_exec instance, node, &block
22
22
  else
23
23
  raise ArgumentError, 'No source specified' if source.nil?
24
- source = case [source.class]
25
- when [Symbol]
26
- source.to_s
27
- when [Array]
28
- source.join('/')
29
- else
30
- source.to_s
31
- end
32
- instance[target] = node.search(source).send(getter).send(matcher)
24
+ instance[target] = node.search(convert_source(source)).send(getter).send(matcher)
33
25
  end
34
26
  if null
35
27
  raise XmlDsl::ParseError, "#{target} is empty. Node: #{node}" if instance[target].nil? || instance[target] == ""
@@ -39,5 +31,26 @@ module XmlDsl
39
31
  def error_handle(exception, node, parser, &block)
40
32
  parser.instance_exec exception, node, &block
41
33
  end
34
+
35
+ def before_parse?(node, parser, key = nil, &block)
36
+ if block_given?
37
+ parser.instance_exec node, &block
38
+ else
39
+ raise ArgumentError, 'Key to check is nil' if key.nil?
40
+ !node.search(convert_source(key)).empty?
41
+ end
42
+ end
43
+
44
+ private
45
+ def convert_source(source)
46
+ case [source.class]
47
+ when [Symbol]
48
+ source.to_s
49
+ when [Array]
50
+ source.join('/')
51
+ else
52
+ source.to_s
53
+ end
54
+ end
42
55
  end
43
56
  end
@@ -23,6 +23,11 @@ module XmlDsl
23
23
  raise ArgumentError, "If there is no @xml in parser, pass it to iterate" if xml_obj.nil?
24
24
  xml_obj.search(_xml_root_path).each do |node|
25
25
  begin
26
+ valid = _xml_parse_callbacks[:before_parsers].map do |bm|
27
+ bm.call node, self
28
+ end.reduce(true, :&)
29
+ next unless valid
30
+ # mapping
26
31
  instance = _xml_target_class.new
27
32
  _xml_parse_callbacks[:readers].each do |bm|
28
33
  bm.call instance, node, self
@@ -1,3 +1,3 @@
1
1
  module XmlDsl
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -28,14 +28,27 @@ module XmlDsl
28
28
  @owner.instance_variable_set :@xml_parser, self
29
29
  end
30
30
 
31
+ # Field for parse definition
32
+ # receives args: target, source = nil, getter: :text, matcher: :to_s, null: false
33
+ # or block with |instance, node|
31
34
  def field(*args, &block)
32
35
  callbacks[:readers] << XmlDsl::BlockMethod.new(:field, *args, &block)
33
36
  end
34
37
 
38
+ # Error handler for automatic or manually raised XmlDsl::ParseError exceptions
39
+ # receives block with two args error and node, that caused the error to occur
40
+ # block with |exception, node|
35
41
  def error_handle(*args, &block)
36
42
  callbacks[:error_handlers] << XmlDsl::BlockMethod.new(:error_handle, *args, &block)
37
43
  end
38
44
 
45
+ # Validation like block
46
+ # receives key: symbol, string, or array of similar
47
+ # returns bool if true - normal, false - skip this node
48
+ def before_parse?(*args, &block)
49
+ callbacks[:before_parsers] << XmlDsl::BlockMethod.new(:before_parse?, *args, &block)
50
+ end
51
+
39
52
  def setup_parser_instance(instance)
40
53
  state_lock.synchronize do
41
54
  instance.instance_variable_set :@_xml_root_path, root_path
@@ -35,7 +35,9 @@
35
35
  <area type="total">30</area>
36
36
  <area type="live">17</area>
37
37
  <area type="kitchen">7</area>
38
+ <area type="hobby">42</area>
38
39
  </areas>
39
40
  <magick>woodoo</magick>
41
+ <jim>Jarmush</jim>
40
42
  </offer>
41
43
  </root>
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
  require 'support/xml'
3
3
 
4
4
  describe 'Example Xml Mapper Spec' do
5
- context 'normal parser' do
5
+ context 'basic parser' do
6
6
  before(:each) do
7
7
  clazz = Class.new
8
8
  clazz.class_eval do
@@ -100,6 +100,37 @@ describe 'Example Xml Mapper Spec' do
100
100
  expect(@external_obj).to receive(:notify).with(kind_of(Nokogiri::XML::Element)).once
101
101
  @parser.iterate
102
102
  end
103
+ end
104
+
105
+ context 'Parser with before_parse validation (good)' do
106
+ before(:each) do
107
+ clazz = Class.new
108
+ @external_obj = double
109
+ clazz.class_eval do
110
+ attr_accessor :xml, :external
111
+ def initialize(xml, external)
112
+ self.xml = xml
113
+ self.external = external
114
+ end
115
+
116
+ define_xml_parser Hash, :root, :offer do
117
+
118
+ before_parse? do |node|
119
+ !node.search('magick').empty?
120
+ end
121
+
122
+ before_parse? :jim
123
+ before_parse? [:areas, 'area[type=hobby]']
124
+
125
+ field :id, :id, matcher: :to_i
126
+ field :minutes, :distance, matcher: :to_i
127
+ end
128
+ end
129
+ @parser = clazz.new some_xml, @external_obj
130
+ end
103
131
 
132
+ it 'returns only one object' do
133
+ expect(@parser.iterate(acc:[]).length).to eql(1)
134
+ end
104
135
  end
105
136
  end
@@ -52,6 +52,10 @@ describe XmlDsl do
52
52
  expect { in_definition { error_handle } }.to change(xml_parser.callbacks[:error_handlers], :length).by(1)
53
53
  end
54
54
 
55
+ it 'defining before_parse is put inside before_parsers' do
56
+ expect { in_definition { before_parse? {} } }.to change(xml_parser.callbacks[:before_parsers], :length).by(1)
57
+ end
58
+
55
59
  def in_definition(&block)
56
60
  xml_parser.instance_eval &block
57
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xml_dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladislav Bogomolov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-17 00:00:00.000000000 Z
11
+ date: 2014-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri