decontaminate 0.2.0 → 0.2.1

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: 7a19c276660c214e8f2048ee4b7368403c91ccb3
4
- data.tar.gz: ef6acef5a324da44451220877c59b9db9ebd3432
3
+ metadata.gz: f731111d47eb751ba591ab27befd41721b22ab09
4
+ data.tar.gz: 4355d58ea218c7ea312e50ccd37bc4dd314345a9
5
5
  SHA512:
6
- metadata.gz: 893c0c7b972eafed7c7afda763602e3f3ef177da07350c39f888fd430aeda37828fa6ee5c5b72ba499279060261c6a9195648298bb69f0c13fc2a63c495dcaf9
7
- data.tar.gz: e6ce0f2510bf0ca46eff1e5eff0ac772903b2f42cd7e0c8e57148a0719d04be5a5275aa694d539c8146ba8830b6b62ad01c970a2a6585dd4bb1a631ee942dc0e
6
+ metadata.gz: 95e52b38d6260c8789ebedab7a56efa09e51464eefce1e02ac56adc3d82c8eea6062da2fabcb17e1cee2a675bc4359e94dd515dc676e38fa21857ee0396c2598
7
+ data.tar.gz: 1c6d7a83b722b26fc570dd4198e0b6ef3c6bd88c77bf6a3e0c759163da1bfecb44bbec44d000517765627652096465817c8e3250e7f743ad610d2ac6b99c1984
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Decontaminate
1
+ # Decontaminate [![Gem Version](https://badge.fury.io/rb/decontaminate.svg)](https://badge.fury.io/rb/decontaminate) [![Build Status](https://travis-ci.org/lexi-lambda/decontaminate.svg?branch=0.2.0)](https://travis-ci.org/lexi-lambda/decontaminate)
2
2
 
3
3
  Decontaminate is a tool for extracting information from large, potentially nested XML documents. It provides a simple Ruby DSL for selecting values from Nokogiri objects and storing the results in JSON-like Ruby hashes and arrays.
4
4
 
@@ -78,6 +78,19 @@ scalar 'RatingPercentage', key: 'rating_ratio', type: :float do |percentage|
78
78
  end
79
79
  ```
80
80
 
81
+ Transformer blocks are evaluated in the context of the decontaminator instance, so instance methods can be called. Additionally, it is possible to call instance methods as transformers directly without needing to pass a block by passing the name of the method as the `transformer:` keyword argument.
82
+
83
+ ```ruby
84
+ scalar 'RatingPercentage',
85
+ key: 'rating_ratio',
86
+ type: :float,
87
+ transformer: :percentage_to_ratio
88
+
89
+ def percentage_to_ratio(percentage)
90
+ percentage && percentage / 100.0
91
+ end
92
+ ```
93
+
81
94
  ### Nested Values
82
95
 
83
96
  It's also possible to specify nested or even deeply nested hashes with the `hash` class method:
@@ -195,6 +208,8 @@ tuple ['Height/text()', 'Height/@units'], key: 'height_cm' do |height, units|
195
208
  end
196
209
  ```
197
210
 
211
+ Tuples also support the shorthand `transformer:` argument that `scalar` and `scalars` support.
212
+
198
213
  ### Flattening nested data
199
214
 
200
215
  Since source data is sometimes more nested than is desired, the `with` method is a helper for scoping decontamination directives to a given XML element without increasing the nesting depth of the resulting object. Like `hash`, it accepts an XPath and a block, but the attributes created from within the block will not be wrapped in a hash.
@@ -8,11 +8,11 @@ module Decontaminate
8
8
  @decoder = decoder
9
9
  end
10
10
 
11
- def decode(xml_node)
11
+ def decode(this, xml_node)
12
12
  children = xml_node && xml_node.xpath(xpath)
13
13
  return [] unless children
14
14
  children.map do |child|
15
- decoder.decode child
15
+ decoder.decode this, child
16
16
  end
17
17
  end
18
18
  end
@@ -8,9 +8,9 @@ module Decontaminate
8
8
  @decoder = decoder
9
9
  end
10
10
 
11
- def decode(xml_node)
11
+ def decode(this, xml_node)
12
12
  child = xml_node && xml_node.at_xpath(xpath)
13
- decoder.decode child
13
+ decoder.decode this, child
14
14
  end
15
15
  end
16
16
  end
@@ -8,9 +8,9 @@ module Decontaminate
8
8
  @decontaminator = decontaminator
9
9
  end
10
10
 
11
- def decode(xml_node)
11
+ def decode(this, xml_node)
12
12
  child = xml_node && xml_node.at_xpath(xpath)
13
- decontaminator.new(child).as_json
13
+ decontaminator.new(child, instance: this).as_json
14
14
  end
15
15
  end
16
16
  end
@@ -9,9 +9,9 @@ module Decontaminate
9
9
  @transformer = transformer
10
10
  end
11
11
 
12
- def decode(xml_node)
12
+ def decode(this, xml_node)
13
13
  value = value_from_xml_node xml_node
14
- value = transformer.call value if transformer
14
+ value = this.instance_exec(value, &transformer) if transformer
15
15
  value
16
16
  end
17
17
 
@@ -9,13 +9,13 @@ module Decontaminate
9
9
  @transformer = transformer
10
10
  end
11
11
 
12
- def decode(xml_node)
12
+ def decode(this, xml_node)
13
13
  xml_nodes = xpaths.map { |xpath| xml_node && xml_node.at_xpath(xpath) }
14
14
  tuple = xml_nodes.map do |element_node|
15
- decoder.decode element_node
15
+ decoder.decode this, element_node
16
16
  end
17
17
 
18
- tuple = transformer.call(*tuple) if transformer
18
+ tuple = this.instance_exec(*tuple, &transformer) if transformer
19
19
 
20
20
  tuple
21
21
  end
@@ -22,13 +22,24 @@ module Decontaminate
22
22
  end
23
23
  end
24
24
 
25
- def scalar(xpath, type: :string, key: infer_key(xpath), &block)
25
+ def scalar(xpath,
26
+ type: :string,
27
+ key: infer_key(xpath),
28
+ transformer: nil,
29
+ &block)
30
+ block ||= self_proc_for_method transformer
26
31
  add_decoder key, Decontaminate::Decoder::Scalar.new(xpath, type, block)
27
32
  end
28
33
 
29
- def scalars(xpath = nil, path: nil, type: :string, key: nil, &block)
34
+ def scalars(xpath = nil,
35
+ path: nil,
36
+ type: :string,
37
+ key: nil,
38
+ transformer: nil,
39
+ &block)
30
40
  resolved_path = path || infer_plural_path(xpath)
31
41
  key ||= infer_key(path || xpath)
42
+ block ||= self_proc_for_method transformer
32
43
 
33
44
  singular = Decontaminate::Decoder::Scalar.new('.', type, block)
34
45
  decoder = Decontaminate::Decoder::Array.new(resolved_path, singular)
@@ -36,9 +47,16 @@ module Decontaminate
36
47
  add_decoder key, decoder
37
48
  end
38
49
 
39
- def tuple(paths, key:, type: :string, &block)
50
+ def tuple(paths,
51
+ key:,
52
+ type: :string,
53
+ transformer: nil,
54
+ &block)
55
+ block ||= self_proc_for_method transformer
56
+
40
57
  scalar = Decontaminate::Decoder::Scalar.new('.', type, nil)
41
58
  decoder = Decontaminate::Decoder::Tuple.new(paths, scalar, block)
59
+
42
60
  add_decoder key, decoder
43
61
  end
44
62
 
@@ -84,12 +102,19 @@ module Decontaminate
84
102
  def infer_plural_path(xpath)
85
103
  xpath + '/' + xpath.split('/').last.singularize
86
104
  end
105
+
106
+ private
107
+
108
+ def self_proc_for_method(sym)
109
+ sym && proc { |*args| send sym, *args }
110
+ end
87
111
  end
88
112
 
89
113
  attr_reader :xml_node
90
114
 
91
- def initialize(xml_node)
115
+ def initialize(xml_node, instance: nil)
92
116
  @xml_node = xml_node
117
+ @instance = instance
93
118
  end
94
119
 
95
120
  def as_json
@@ -97,7 +122,7 @@ module Decontaminate
97
122
 
98
123
  root_node = xml_node && xml_node.at_xpath(root)
99
124
  decoders.each do |key, decoder|
100
- acc[key] = decoder.decode root_node
125
+ acc[key] = decoder.decode instance, root_node
101
126
  end
102
127
 
103
128
  acc
@@ -105,6 +130,12 @@ module Decontaminate
105
130
 
106
131
  private
107
132
 
133
+ # The canonical instance that all blocks should run within. Child
134
+ # (anonymous) decontaminators should delegate to the parent.
135
+ def instance
136
+ @instance || self
137
+ end
138
+
108
139
  def decoders
109
140
  self.class.decoders
110
141
  end
@@ -1,3 +1,3 @@
1
1
  module Decontaminate
2
- VERSION = '0.2.0'
2
+ VERSION = '0.2.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decontaminate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis King