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