transproc 0.2.4 → 0.3.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +30 -0
- data/README.md +33 -15
- data/lib/transproc.rb +23 -14
- data/lib/transproc/array.rb +21 -15
- data/lib/transproc/class.rb +7 -3
- data/lib/transproc/coercions.rb +15 -11
- data/lib/transproc/composer.rb +26 -2
- data/lib/transproc/conditional.rb +7 -3
- data/lib/transproc/error.rb +7 -1
- data/lib/transproc/function.rb +28 -5
- data/lib/transproc/functions.rb +5 -0
- data/lib/transproc/hash.rb +102 -26
- data/lib/transproc/recursion.rb +11 -7
- data/lib/transproc/registry.rb +53 -55
- data/lib/transproc/rspec.rb +59 -0
- data/lib/transproc/store.rb +94 -0
- data/lib/transproc/support/deprecations.rb +11 -0
- data/lib/transproc/version.rb +1 -1
- data/spec/unit/array_transformations_spec.rb +29 -25
- data/spec/unit/class_transformations_spec.rb +2 -2
- data/spec/unit/coercions_spec.rb +13 -13
- data/spec/unit/composer_spec.rb +13 -2
- data/spec/unit/conditional_spec.rb +3 -1
- data/spec/unit/function_not_found_error_spec.rb +20 -0
- data/spec/unit/function_spec.rb +49 -8
- data/spec/unit/hash_transformations_spec.rb +101 -63
- data/spec/unit/recursion_spec.rb +12 -6
- data/spec/unit/registry_spec.rb +65 -55
- data/spec/unit/store_spec.rb +148 -0
- data/spec/unit/transproc_spec.rb +8 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3020e57756005b16449b171dc8532bd2c39887e
|
4
|
+
data.tar.gz: 06f27a81c36eec5993c51e64b58d440355ea1a12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76b51f3ed36099dfa1410ac9aed768edab31275cc2057b50ee3e91b0795c36a8db2e030163c38f3be33fce5480b6523b3766f911951ed7026364310384b85412
|
7
|
+
data.tar.gz: 17d92360f7aaddc1f0a00fcf240f7402d9cf3419ed1c3b1a3e93e73b7a5781cfc8c8f84757b8b52529f9dadc7323e6d3302c840f017b60f80514b30ded93e05a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,33 @@
|
|
1
|
+
## v0.3.0 2015-07-12
|
2
|
+
|
3
|
+
This release deprecates a couple of APIs and changes the way functions can be
|
4
|
+
accessed. The global `Transproc()` function registry is now deprecated and you
|
5
|
+
should define your own function registry via `extend Transproc::Registry` and its
|
6
|
+
`import` interface. See API docs for the details.
|
7
|
+
|
8
|
+
Proper deprecation warnings will appear as this is still a backward-compatible
|
9
|
+
release, however, please update to the new API as the global registry will be gone
|
10
|
+
in 1.0.0.
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
* `HashTransformations.eval_values` which evaluates callable values in a hash
|
15
|
+
recursively (solnic)
|
16
|
+
* `HashTransformations.deep_symbolize_keys` which, surprise surprise, symbolizes
|
17
|
+
keys in a hash, recursively (solnic)
|
18
|
+
* Shared examples `:transforming_immutable_data` and `:mutating_input_data`
|
19
|
+
to specify transformations in RSpec (nepalez)
|
20
|
+
|
21
|
+
### Changed
|
22
|
+
|
23
|
+
* `Transproc::Registry` now uses singleton methods that can be imported from
|
24
|
+
arbitrary modules via `import` interface (nepalez)
|
25
|
+
* Updated all built-in modules to the new registry API (nepalez + solnic)
|
26
|
+
* `Transproc()` has been deprecated (solnic)
|
27
|
+
* `Transproc::Helper` has been deprecated (solnic)
|
28
|
+
|
29
|
+
[Compare v0.2.4...HEAD](https://github.com/solnic/transproc/compare/v0.2.4...HEAD)
|
30
|
+
|
1
31
|
## v0.2.4 2015-06-20
|
2
32
|
|
3
33
|
### Added
|
data/README.md
CHANGED
@@ -38,14 +38,32 @@ Or install it yourself as:
|
|
38
38
|
``` ruby
|
39
39
|
require 'json'
|
40
40
|
require 'transproc/all'
|
41
|
+
require 'inflecto'
|
41
42
|
|
42
|
-
#
|
43
|
-
|
43
|
+
# create your own local registry for transformation functions
|
44
|
+
module Functions
|
45
|
+
extend Transproc::Registry
|
46
|
+
end
|
47
|
+
|
48
|
+
# import necessary functions from external modules
|
49
|
+
module Functions
|
50
|
+
# ...
|
51
|
+
|
52
|
+
# all transformations available in the imported module
|
53
|
+
import Transproc::HashTransforations
|
54
|
+
import Transproc::ArrayTransformations
|
44
55
|
|
45
|
-
|
46
|
-
|
56
|
+
# only specific transformation (renamed into the desired local name)
|
57
|
+
import :camelize, from: Inflecto, as: :camel_case
|
58
|
+
end
|
59
|
+
|
60
|
+
# use imported transformation
|
61
|
+
transformation = Functions[:camel_case]
|
62
|
+
transformation.call 'i_am_a_camel'
|
63
|
+
# => "IAmACamel"
|
47
64
|
|
48
|
-
|
65
|
+
transformation = Functions[:map_array, Functions[:symbolize_keys] >> Functions[:rename_keys, user_name: :user]]
|
66
|
+
transformation >>= Functions[:wrap, :address, [:city, :street, :zipcode]]
|
49
67
|
transformation.call(
|
50
68
|
[
|
51
69
|
{ 'user_name' => 'Jane',
|
@@ -56,22 +74,22 @@ transformation.call(
|
|
56
74
|
)
|
57
75
|
# => [{:user=>"Jane", :address=>{:city=>"NYC", :street=>"Street 1", :zipcode=>"123"}}]
|
58
76
|
|
59
|
-
#
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# => "[{\"name\":\"Jane\"}]"
|
77
|
+
# define your own composable transformation easily
|
78
|
+
transformation = Functions[-> v { JSON.dump(v) }]
|
79
|
+
transformation.call(name: 'Jane')
|
80
|
+
# => "{\"name\":\"Jane\"}"
|
64
81
|
|
65
|
-
# ...or
|
66
|
-
module
|
67
|
-
|
82
|
+
# ...or add it to registered functions via singleton method of the registry
|
83
|
+
module Functions
|
84
|
+
# ...
|
68
85
|
|
69
|
-
def load_json(v)
|
86
|
+
def self.load_json(v)
|
70
87
|
JSON.load(v)
|
71
88
|
end
|
72
89
|
end
|
73
90
|
|
74
|
-
|
91
|
+
transformation = Functions[:load_json] >> Functions[:map_array, Functions[:symbolize_keys]]
|
92
|
+
transformation.call('[{"name":"Jane"}]')
|
75
93
|
# => [{ :name => "Jane" }]
|
76
94
|
```
|
77
95
|
|
data/lib/transproc.rb
CHANGED
@@ -3,10 +3,17 @@ require 'transproc/function'
|
|
3
3
|
require 'transproc/functions'
|
4
4
|
require 'transproc/composer'
|
5
5
|
require 'transproc/error'
|
6
|
+
require 'transproc/store'
|
6
7
|
require 'transproc/registry'
|
8
|
+
require 'transproc/support/deprecations'
|
7
9
|
|
8
10
|
module Transproc
|
9
|
-
|
11
|
+
# Function registry
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def self.functions
|
15
|
+
@_functions ||= {}
|
16
|
+
end
|
10
17
|
|
11
18
|
# Register a new function
|
12
19
|
#
|
@@ -19,9 +26,9 @@ module Transproc
|
|
19
26
|
# @return [Function]
|
20
27
|
#
|
21
28
|
# @api public
|
22
|
-
def register(*args, &block)
|
29
|
+
def self.register(*args, &block)
|
23
30
|
name, fn = *args
|
24
|
-
if functions.include?
|
31
|
+
if functions.include? name
|
25
32
|
raise FunctionAlreadyRegisteredError, "Function #{name} is already defined"
|
26
33
|
end
|
27
34
|
functions[name] = fn || block
|
@@ -32,17 +39,14 @@ module Transproc
|
|
32
39
|
# @param [Symbol] name The name of the registered function
|
33
40
|
#
|
34
41
|
# @api private
|
35
|
-
def [](name)
|
36
|
-
functions.fetch(name) {
|
37
|
-
raise FunctionNotFoundError, "No registered function for #{name}"
|
38
|
-
}
|
39
|
-
end
|
42
|
+
def self.[](name, *args)
|
43
|
+
fn = functions.fetch(name) { raise FunctionNotFoundError.new(name) }
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
if args.any?
|
46
|
+
fn.with(*args)
|
47
|
+
else
|
48
|
+
fn
|
49
|
+
end
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -63,10 +67,15 @@ require 'transproc/hash'
|
|
63
67
|
#
|
64
68
|
# @api public
|
65
69
|
def Transproc(fn, *args)
|
70
|
+
Transproc::Deprecations.announce(
|
71
|
+
'Transproc()',
|
72
|
+
'Define your own function registry using Transproc::Registry extension'
|
73
|
+
)
|
74
|
+
|
66
75
|
case fn
|
67
76
|
when Proc then Transproc::Function.new(fn, args: args)
|
68
77
|
when Symbol
|
69
|
-
fun = Transproc[fn]
|
78
|
+
fun = Transproc[fn, *args]
|
70
79
|
case fun
|
71
80
|
when Transproc::Function, Transproc::Composite then fun
|
72
81
|
else Transproc::Function.new(fun, args: args)
|
data/lib/transproc/array.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'transproc/coercions'
|
2
|
+
require 'transproc/hash'
|
2
3
|
|
3
4
|
module Transproc
|
4
5
|
# Transformation functions for Array objects
|
@@ -20,7 +21,7 @@ module Transproc
|
|
20
21
|
#
|
21
22
|
# @api public
|
22
23
|
module ArrayTransformations
|
23
|
-
extend
|
24
|
+
extend Registry
|
24
25
|
|
25
26
|
# Map array values using transformation function
|
26
27
|
#
|
@@ -36,7 +37,7 @@ module Transproc
|
|
36
37
|
# @return [Array]
|
37
38
|
#
|
38
39
|
# @api public
|
39
|
-
def map_array(array, fn)
|
40
|
+
def self.map_array(array, fn)
|
40
41
|
map_array!(Array[*array], fn)
|
41
42
|
end
|
42
43
|
|
@@ -45,7 +46,7 @@ module Transproc
|
|
45
46
|
# @see ArrayTransformations.map_array
|
46
47
|
#
|
47
48
|
# @api public
|
48
|
-
def map_array!(array, fn)
|
49
|
+
def self.map_array!(array, fn)
|
49
50
|
array.map! { |value| fn[value] }
|
50
51
|
end
|
51
52
|
|
@@ -64,8 +65,9 @@ module Transproc
|
|
64
65
|
# @return [Array]
|
65
66
|
#
|
66
67
|
# @api public
|
67
|
-
def wrap(array, key, keys)
|
68
|
-
|
68
|
+
def self.wrap(array, key, keys)
|
69
|
+
nest = HashTransformations[:nest, key, keys]
|
70
|
+
map_array(array, nest)
|
69
71
|
end
|
70
72
|
|
71
73
|
# Group array values using provided root key and value keys
|
@@ -86,12 +88,12 @@ module Transproc
|
|
86
88
|
# @return [Array]
|
87
89
|
#
|
88
90
|
# @api public
|
89
|
-
def group(array, key, keys)
|
91
|
+
def self.group(array, key, keys)
|
90
92
|
grouped = Hash.new { |h, k| h[k] = [] }
|
91
93
|
array.each do |hash|
|
92
94
|
hash = Hash[hash]
|
93
95
|
|
94
|
-
old_group =
|
96
|
+
old_group = Coercions.to_tuples(hash.delete(key))
|
95
97
|
new_group = keys.inject({}) { |a, e| a.merge(e => hash.delete(e)) }
|
96
98
|
|
97
99
|
grouped[hash] << old_group.map { |item| item.merge(new_group) }
|
@@ -121,7 +123,7 @@ module Transproc
|
|
121
123
|
# @return [Array]
|
122
124
|
#
|
123
125
|
# @api public
|
124
|
-
def ungroup(array, key, keys)
|
126
|
+
def self.ungroup(array, key, keys)
|
125
127
|
array.flat_map { |item| HashTransformations.split(item, key, keys) }
|
126
128
|
end
|
127
129
|
|
@@ -139,7 +141,7 @@ module Transproc
|
|
139
141
|
# @return [Array<Hash>]
|
140
142
|
#
|
141
143
|
# @api public
|
142
|
-
def combine(array, mappings)
|
144
|
+
def self.combine(array, mappings)
|
143
145
|
root, groups = array
|
144
146
|
|
145
147
|
cache = Hash.new { |h, k| h[k] = {} }
|
@@ -189,7 +191,7 @@ module Transproc
|
|
189
191
|
# @return [Array]
|
190
192
|
#
|
191
193
|
# @api public
|
192
|
-
def extract_key(array, key)
|
194
|
+
def self.extract_key(array, key)
|
193
195
|
extract_key!(Array[*array], key)
|
194
196
|
end
|
195
197
|
|
@@ -198,7 +200,7 @@ module Transproc
|
|
198
200
|
# @see ArrayTransformations.extract_key
|
199
201
|
#
|
200
202
|
# @api public
|
201
|
-
def extract_key!(array, key)
|
203
|
+
def self.extract_key!(array, key)
|
202
204
|
map_array!(array, -> v { v[key] })
|
203
205
|
end
|
204
206
|
|
@@ -217,7 +219,7 @@ module Transproc
|
|
217
219
|
# @return [Array]
|
218
220
|
#
|
219
221
|
# @api public
|
220
|
-
def insert_key(array, key)
|
222
|
+
def self.insert_key(array, key)
|
221
223
|
insert_key!(Array[*array], key)
|
222
224
|
end
|
223
225
|
|
@@ -226,7 +228,7 @@ module Transproc
|
|
226
228
|
# @see ArrayTransformations.insert_key
|
227
229
|
#
|
228
230
|
# @api public
|
229
|
-
def insert_key!(array, key)
|
231
|
+
def self.insert_key!(array, key)
|
230
232
|
map_array!(array, -> v { { key => v } })
|
231
233
|
end
|
232
234
|
|
@@ -238,7 +240,7 @@ module Transproc
|
|
238
240
|
#
|
239
241
|
# @api public
|
240
242
|
#
|
241
|
-
def add_keys(array, keys)
|
243
|
+
def self.add_keys(array, keys)
|
242
244
|
add_keys!(Array[*array], keys)
|
243
245
|
end
|
244
246
|
|
@@ -247,9 +249,13 @@ module Transproc
|
|
247
249
|
# @see ArrayTransformations.add_keys
|
248
250
|
#
|
249
251
|
# @api public
|
250
|
-
def add_keys!(array, keys)
|
252
|
+
def self.add_keys!(array, keys)
|
251
253
|
base = keys.inject({}) { |a, e| a.merge(e => nil) }
|
252
254
|
map_array!(array, -> v { base.merge(v) })
|
253
255
|
end
|
256
|
+
|
257
|
+
# @deprecated Register methods globally
|
258
|
+
(methods - Registry.methods - Registry.instance_methods)
|
259
|
+
.each { |name| Transproc.register name, t(name) }
|
254
260
|
end
|
255
261
|
end
|
data/lib/transproc/class.rb
CHANGED
@@ -13,7 +13,7 @@ module Transproc
|
|
13
13
|
#
|
14
14
|
# @api public
|
15
15
|
module ClassTransformations
|
16
|
-
extend
|
16
|
+
extend Registry
|
17
17
|
|
18
18
|
# Inject given arguments into the constructor of the class
|
19
19
|
#
|
@@ -26,7 +26,7 @@ module Transproc
|
|
26
26
|
# @return [Object] An instance of the given klass
|
27
27
|
#
|
28
28
|
# @api public
|
29
|
-
def constructor_inject(*args, klass)
|
29
|
+
def self.constructor_inject(*args, klass)
|
30
30
|
klass.new(*args)
|
31
31
|
end
|
32
32
|
|
@@ -41,12 +41,16 @@ module Transproc
|
|
41
41
|
# @return [Object]
|
42
42
|
#
|
43
43
|
# @api public
|
44
|
-
def set_ivars(ivar_hash, klass)
|
44
|
+
def self.set_ivars(ivar_hash, klass)
|
45
45
|
object = klass.allocate
|
46
46
|
ivar_hash.each do |ivar_name, ivar_value|
|
47
47
|
object.instance_variable_set("@#{ivar_name}", ivar_value)
|
48
48
|
end
|
49
49
|
object
|
50
50
|
end
|
51
|
+
|
52
|
+
# @deprecated Register methods globally
|
53
|
+
(methods - Registry.methods - Registry.instance_methods)
|
54
|
+
.each { |name| Transproc.register name, t(name) }
|
51
55
|
end
|
52
56
|
end
|
data/lib/transproc/coercions.rb
CHANGED
@@ -8,7 +8,7 @@ module Transproc
|
|
8
8
|
#
|
9
9
|
# @api public
|
10
10
|
module Coercions
|
11
|
-
extend
|
11
|
+
extend Registry
|
12
12
|
|
13
13
|
TRUE_VALUES = [true, 1, '1', 'on', 't', 'true', 'y', 'yes'].freeze
|
14
14
|
FALSE_VALUES = [false, 0, '0', 'off', 'f', 'false', 'n', 'no'].freeze
|
@@ -28,7 +28,7 @@ module Transproc
|
|
28
28
|
# @return [String]
|
29
29
|
#
|
30
30
|
# @api public
|
31
|
-
def to_string(value)
|
31
|
+
def self.to_string(value)
|
32
32
|
value.to_s
|
33
33
|
end
|
34
34
|
|
@@ -43,7 +43,7 @@ module Transproc
|
|
43
43
|
# @return [Symbol]
|
44
44
|
#
|
45
45
|
# @api public
|
46
|
-
def to_symbol(value)
|
46
|
+
def self.to_symbol(value)
|
47
47
|
value.to_sym
|
48
48
|
end
|
49
49
|
|
@@ -58,7 +58,7 @@ module Transproc
|
|
58
58
|
# @return [Integer]
|
59
59
|
#
|
60
60
|
# @api public
|
61
|
-
def to_integer(value)
|
61
|
+
def self.to_integer(value)
|
62
62
|
value.to_i
|
63
63
|
end
|
64
64
|
|
@@ -73,7 +73,7 @@ module Transproc
|
|
73
73
|
# @return [Float]
|
74
74
|
#
|
75
75
|
# @api public
|
76
|
-
def to_float(value)
|
76
|
+
def self.to_float(value)
|
77
77
|
value.to_f
|
78
78
|
end
|
79
79
|
|
@@ -88,7 +88,7 @@ module Transproc
|
|
88
88
|
# @return [Decimal]
|
89
89
|
#
|
90
90
|
# @api public
|
91
|
-
def to_decimal(value)
|
91
|
+
def self.to_decimal(value)
|
92
92
|
value.to_d
|
93
93
|
end
|
94
94
|
|
@@ -105,7 +105,7 @@ module Transproc
|
|
105
105
|
# @return [TrueClass,FalseClass]
|
106
106
|
#
|
107
107
|
# @api public
|
108
|
-
def to_boolean(value)
|
108
|
+
def self.to_boolean(value)
|
109
109
|
BOOLEAN_MAP.fetch(value)
|
110
110
|
end
|
111
111
|
|
@@ -120,7 +120,7 @@ module Transproc
|
|
120
120
|
# @return [Date]
|
121
121
|
#
|
122
122
|
# @api public
|
123
|
-
def to_date(value)
|
123
|
+
def self.to_date(value)
|
124
124
|
Date.parse(value)
|
125
125
|
end
|
126
126
|
|
@@ -135,7 +135,7 @@ module Transproc
|
|
135
135
|
# @return [Time]
|
136
136
|
#
|
137
137
|
# @api public
|
138
|
-
def to_time(value)
|
138
|
+
def self.to_time(value)
|
139
139
|
Time.parse(value)
|
140
140
|
end
|
141
141
|
|
@@ -150,7 +150,7 @@ module Transproc
|
|
150
150
|
# @return [DateTime]
|
151
151
|
#
|
152
152
|
# @api public
|
153
|
-
def to_datetime(value)
|
153
|
+
def self.to_datetime(value)
|
154
154
|
DateTime.parse(value)
|
155
155
|
end
|
156
156
|
|
@@ -168,10 +168,14 @@ module Transproc
|
|
168
168
|
#
|
169
169
|
# @return [Array<Hash>]
|
170
170
|
#
|
171
|
-
def to_tuples(value)
|
171
|
+
def self.to_tuples(value)
|
172
172
|
array = value.is_a?(Array) ? Array[*value] : [{}]
|
173
173
|
array.select! { |item| item.is_a?(Hash) }
|
174
174
|
array.any? ? array : [{}]
|
175
175
|
end
|
176
|
+
|
177
|
+
# @deprecated Register methods globally
|
178
|
+
(methods - Registry.methods - Registry.instance_methods)
|
179
|
+
.each { |name| Transproc.register name, t(name) }
|
176
180
|
end
|
177
181
|
end
|