transproc 1.0.3 → 1.1.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/.codeclimate.yml +15 -0
- data/.gitignore +3 -0
- data/.travis.yml +10 -10
- data/CHANGELOG.md +14 -2
- data/Gemfile +5 -17
- data/lib/transproc.rb +3 -4
- data/lib/transproc/all.rb +2 -0
- data/lib/transproc/array.rb +2 -0
- data/lib/transproc/array/combine.rb +2 -0
- data/lib/transproc/class.rb +2 -0
- data/lib/transproc/coercions.rb +2 -0
- data/lib/transproc/compiler.rb +45 -0
- data/lib/transproc/composer.rb +2 -0
- data/lib/transproc/composite.rb +2 -0
- data/lib/transproc/conditional.rb +2 -0
- data/lib/transproc/constants.rb +5 -0
- data/lib/transproc/error.rb +2 -0
- data/lib/transproc/function.rb +2 -0
- data/lib/transproc/functions.rb +2 -0
- data/lib/transproc/hash.rb +31 -0
- data/lib/transproc/proc.rb +2 -0
- data/lib/transproc/recursion.rb +2 -0
- data/lib/transproc/registry.rb +1 -0
- data/lib/transproc/store.rb +1 -0
- data/lib/transproc/support/deprecations.rb +2 -0
- data/lib/transproc/transformer.rb +7 -1
- data/lib/transproc/transformer/class_interface.rb +31 -65
- data/lib/transproc/transformer/deprecated/class_interface.rb +80 -0
- data/lib/transproc/transformer/dsl.rb +51 -0
- data/lib/transproc/version.rb +3 -1
- data/spec/spec_helper.rb +5 -7
- data/spec/unit/array/combine_spec.rb +3 -1
- data/spec/unit/array_transformations_spec.rb +1 -1
- data/spec/unit/class_transformations_spec.rb +9 -6
- data/spec/unit/coercions_spec.rb +1 -1
- data/spec/unit/composer_spec.rb +1 -1
- data/spec/unit/conditional_spec.rb +1 -1
- data/spec/unit/function_not_found_error_spec.rb +1 -1
- data/spec/unit/function_spec.rb +1 -1
- data/spec/unit/hash_transformations_spec.rb +12 -1
- data/spec/unit/proc_transformations_spec.rb +3 -1
- data/spec/unit/recursion_spec.rb +1 -1
- data/spec/unit/registry_spec.rb +1 -1
- data/spec/unit/store_spec.rb +2 -1
- data/spec/unit/transformer/class_interface_spec.rb +364 -0
- data/spec/unit/transformer/dsl_spec.rb +15 -0
- data/spec/unit/transformer/instance_methods_spec.rb +25 -0
- data/spec/unit/transformer_spec.rb +128 -40
- data/spec/unit/transproc_spec.rb +1 -1
- data/transproc.gemspec +0 -4
- metadata +15 -53
- data/.rubocop.yml +0 -66
- data/.rubocop_todo.yml +0 -11
- data/rakelib/mutant.rake +0 -16
- data/rakelib/rubocop.rake +0 -18
- data/spec/support/mutant.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd2c6ee5f665083297c1fcfd89a5e37d2284e498d6bc3953b88314e9513cbf43
|
4
|
+
data.tar.gz: 6b9a5f270234b26b479095c66187f91fcca9428afb605f75aa9f51b890976eef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c79034b27d317e52be52e98eb0cce057400efc99c05203e16fd39112a911d0bb568511d58dd138bbc32568cf8951fab586dcdf90e3c9bff434b6fd93347044b
|
7
|
+
data.tar.gz: a2086dc6a92e03837412d7665869c1ad516a3a5ce097db1b31224936d767af048eadb32c86e8e0bcf815ef38445f9aed9a878b5f5ca97b5559b3194efa567aec
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
version: "2"
|
2
|
+
|
3
|
+
prepare:
|
4
|
+
fetch:
|
5
|
+
- url: "https://raw.githubusercontent.com/dry-rb/devtools/master/.rubocop.yml"
|
6
|
+
path: ".rubocop.yml"
|
7
|
+
|
8
|
+
exclude_patterns:
|
9
|
+
- "benchmarks/"
|
10
|
+
- "examples/"
|
11
|
+
- "spec/"
|
12
|
+
|
13
|
+
plugins:
|
14
|
+
rubocop:
|
15
|
+
enabled: true
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
dist: trusty
|
2
1
|
language: ruby
|
3
|
-
sudo: required
|
4
2
|
cache: bundler
|
5
3
|
bundler_args: --without tools
|
6
|
-
before_script:
|
4
|
+
before_script:
|
5
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
6
|
+
- chmod +x ./cc-test-reporter
|
7
|
+
- ./cc-test-reporter before-build
|
8
|
+
after_script:
|
9
|
+
- "[ -d coverage ] && ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT"
|
7
10
|
script: 'bundle exec rake spec'
|
8
|
-
after_success:
|
9
|
-
- '[ -d coverage ] && bundle exec codeclimate-test-reporter'
|
10
11
|
rvm:
|
11
12
|
- 2.3.8
|
12
|
-
- 2.
|
13
|
-
- 2.5.
|
14
|
-
- 2.6
|
15
|
-
- jruby-9.2.
|
13
|
+
- 2.6.3
|
14
|
+
- 2.5.5
|
15
|
+
- 2.4.6
|
16
|
+
- jruby-9.2.7.0
|
16
17
|
env:
|
17
18
|
global:
|
18
|
-
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
19
19
|
- COVERAGE='true'
|
20
20
|
notifications:
|
21
21
|
webhooks:
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,23 @@
|
|
1
|
-
# v1.0
|
1
|
+
# v1.1.0 2019-07-18
|
2
|
+
|
3
|
+
This is the last transproc release before the project will be forked to `dry-transformer`.
|
4
|
+
|
5
|
+
## Added
|
6
|
+
|
7
|
+
* New DSL for defining transformers using `define!` method, which now supports instance methods as transformation functions (@solnic)
|
8
|
+
* Simplified transformer class definition - registry is auto-configured and you can use `import` at the transformer class level (@solnic)
|
9
|
+
* New `HashTransformation.deep_stringify_keys` function
|
10
|
+
|
11
|
+
[Compare v1.0.3...v1.1.0](https://github.com/solnic/transproc/compare/v1.0.3...v1.1.0)
|
12
|
+
|
13
|
+
# v1.0.3 2018-12-01
|
2
14
|
|
3
15
|
## Changed
|
4
16
|
|
5
17
|
* [BREAKING] Added minimal Ruby version to the gemspec file. Transproc now works with Ruby 2.3 and above (flash-gordon)
|
6
18
|
* Performance improvements introduced by using new built-in methods in `Hash` (v-kolesnikov + flash-gordon)
|
7
19
|
|
8
|
-
[Compare v1.0.2...
|
20
|
+
[Compare v1.0.2...v1.0.3](https://github.com/solnic/transproc/compare/v1.0.2...v1.0.3)
|
9
21
|
|
10
22
|
# v1.0.2 2017-02-25
|
11
23
|
|
data/Gemfile
CHANGED
@@ -2,27 +2,15 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
gem 'rake'
|
6
|
+
gem 'rspec', '~> 3.8'
|
7
|
+
gem 'dry-equalizer', '~> 0.2'
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
platform :mri do
|
11
|
-
if RUBY_VERSION >= '2.5'
|
12
|
-
gem 'mutant', github: 'mbj/mutant', branch: 'master'
|
13
|
-
gem 'mutant-rspec'
|
14
|
-
end
|
15
|
-
|
16
|
-
gem 'codeclimate-test-reporter', require: false
|
17
|
-
gem 'simplecov', require: false
|
18
|
-
end
|
9
|
+
platform :mri do
|
10
|
+
gem 'simplecov', require: false
|
19
11
|
end
|
20
12
|
|
21
13
|
group :tools do
|
22
|
-
gem 'rubocop', '~> 0.30.0'
|
23
14
|
gem 'byebug', platform: :mri
|
24
15
|
gem 'benchmark-ips'
|
25
|
-
gem 'guard'
|
26
|
-
gem 'guard-rspec'
|
27
|
-
gem 'guard-rubocop'
|
28
16
|
end
|
data/lib/transproc.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'transproc/version'
|
4
|
+
require 'transproc/constants'
|
2
5
|
require 'transproc/function'
|
3
6
|
require 'transproc/functions'
|
4
7
|
require 'transproc/composer'
|
@@ -8,9 +11,5 @@ require 'transproc/registry'
|
|
8
11
|
require 'transproc/transformer'
|
9
12
|
require 'transproc/support/deprecations'
|
10
13
|
|
11
|
-
module Transproc
|
12
|
-
Undefined = Object.new.freeze
|
13
|
-
end
|
14
|
-
|
15
14
|
require 'transproc/array'
|
16
15
|
require 'transproc/hash'
|
data/lib/transproc/all.rb
CHANGED
data/lib/transproc/array.rb
CHANGED
data/lib/transproc/class.rb
CHANGED
data/lib/transproc/coercions.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Transproc
|
4
|
+
# @api private
|
5
|
+
class Compiler
|
6
|
+
InvalidFunctionNameError = Class.new(StandardError)
|
7
|
+
|
8
|
+
attr_reader :registry, :transformer
|
9
|
+
|
10
|
+
def initialize(registry, transformer = nil)
|
11
|
+
@registry = registry
|
12
|
+
@transformer = transformer
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(ast)
|
16
|
+
ast.map(&method(:visit)).reduce(:>>)
|
17
|
+
end
|
18
|
+
|
19
|
+
def visit(node)
|
20
|
+
id, *rest = node
|
21
|
+
public_send(:"visit_#{id}", *rest)
|
22
|
+
end
|
23
|
+
|
24
|
+
def visit_fn(node)
|
25
|
+
name, rest = node
|
26
|
+
args = rest.map { |arg| visit(arg) }
|
27
|
+
|
28
|
+
if registry.contain?(name)
|
29
|
+
registry[name, *args]
|
30
|
+
elsif transformer.respond_to?(name)
|
31
|
+
Function.new(transformer.method(name), name: name, args: args)
|
32
|
+
else
|
33
|
+
raise InvalidFunctionNameError, "function name +#{name}+ is not valid"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def visit_arg(arg)
|
38
|
+
arg
|
39
|
+
end
|
40
|
+
|
41
|
+
def visit_t(node)
|
42
|
+
call(node)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/transproc/composer.rb
CHANGED
data/lib/transproc/composite.rb
CHANGED
data/lib/transproc/error.rb
CHANGED
data/lib/transproc/function.rb
CHANGED
data/lib/transproc/functions.rb
CHANGED
data/lib/transproc/hash.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'transproc/coercions'
|
2
4
|
|
3
5
|
module Transproc
|
@@ -100,6 +102,35 @@ module Transproc
|
|
100
102
|
map_keys(hash, Coercions[:to_string].fn)
|
101
103
|
end
|
102
104
|
|
105
|
+
# Stringify keys in a hash recursively
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
# input = { :foo => "bar", :baz => [{ :one => 1 }] }
|
109
|
+
#
|
110
|
+
# t(:deep_stringify_keys)[input]
|
111
|
+
# # => { "foo" => "bar", "baz" => [{ "one" => 1 }] }
|
112
|
+
#
|
113
|
+
# @param [Hash]
|
114
|
+
#
|
115
|
+
# @return [Hash]
|
116
|
+
#
|
117
|
+
# @api public
|
118
|
+
def self.deep_stringify_keys(hash)
|
119
|
+
hash.each_with_object({}) do |(key, value), output|
|
120
|
+
output[key.to_s] =
|
121
|
+
case value
|
122
|
+
when Hash
|
123
|
+
deep_stringify_keys(value)
|
124
|
+
when Array
|
125
|
+
value.map { |item|
|
126
|
+
item.is_a?(Hash) ? deep_stringify_keys(item) : item
|
127
|
+
}
|
128
|
+
else
|
129
|
+
value
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
103
134
|
if RUBY_VERSION >= '2.4'
|
104
135
|
# Map all values in a hash using transformation function
|
105
136
|
#
|
data/lib/transproc/proc.rb
CHANGED
data/lib/transproc/recursion.rb
CHANGED
data/lib/transproc/registry.rb
CHANGED
data/lib/transproc/store.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'transproc/transformer/class_interface'
|
4
|
+
require 'transproc/transformer/deprecated/class_interface'
|
2
5
|
|
3
6
|
module Transproc
|
4
7
|
# Transfomer class for defining transprocs with a class DSL.
|
@@ -45,6 +48,9 @@ module Transproc
|
|
45
48
|
# @api public
|
46
49
|
class Transformer
|
47
50
|
extend ClassInterface
|
51
|
+
extend Deprecated::ClassInterface
|
52
|
+
|
53
|
+
attr_reader :transproc
|
48
54
|
|
49
55
|
# Execute the transformation pipeline with the given input.
|
50
56
|
#
|
@@ -63,7 +69,7 @@ module Transproc
|
|
63
69
|
#
|
64
70
|
# @api public
|
65
71
|
def call(input)
|
66
|
-
|
72
|
+
transproc.call(input)
|
67
73
|
end
|
68
74
|
end
|
69
75
|
end
|
@@ -1,7 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'transproc/transformer/dsl'
|
4
|
+
|
1
5
|
module Transproc
|
2
6
|
class Transformer
|
3
|
-
# @api
|
7
|
+
# @api public
|
4
8
|
module ClassInterface
|
9
|
+
# @api private
|
10
|
+
attr_reader :dsl
|
11
|
+
|
5
12
|
# Return a base Transproc::Transformer class with the
|
6
13
|
# container configured to the passed argument.
|
7
14
|
#
|
@@ -17,14 +24,18 @@ module Transproc
|
|
17
24
|
#
|
18
25
|
# @api public
|
19
26
|
def [](container)
|
20
|
-
klass = Class.new(
|
27
|
+
klass = Class.new(self)
|
21
28
|
klass.container(container)
|
22
29
|
klass
|
23
30
|
end
|
24
31
|
|
25
32
|
# @api private
|
26
33
|
def inherited(subclass)
|
34
|
+
super
|
35
|
+
|
27
36
|
subclass.container(@container) if defined?(@container)
|
37
|
+
|
38
|
+
subclass.instance_variable_set('@dsl', dsl.dup) if dsl
|
28
39
|
end
|
29
40
|
|
30
41
|
# Get or set the container to resolve transprocs from.
|
@@ -45,41 +56,32 @@ module Transproc
|
|
45
56
|
# @return [Transproc::Registry]
|
46
57
|
#
|
47
58
|
# @api private
|
48
|
-
def container(container =
|
49
|
-
if container
|
50
|
-
|
51
|
-
@container
|
59
|
+
def container(container = Undefined)
|
60
|
+
if container.equal?(Undefined)
|
61
|
+
@container ||= Module.new.extend(Transproc::Registry)
|
52
62
|
else
|
53
63
|
@container = container
|
54
64
|
end
|
55
65
|
end
|
56
66
|
|
57
|
-
# Define an anonymous transproc derived from given Transformer
|
58
|
-
# Evaluates block with transformations and returns initialized transproc.
|
59
|
-
# Does not mutate original Transformer
|
60
|
-
#
|
61
|
-
# @example
|
62
|
-
#
|
63
|
-
# class MyTransformer < Transproc::Transformer[MyContainer]
|
64
|
-
# end
|
65
|
-
#
|
66
|
-
# transproc = MyTransformer.define do
|
67
|
-
# map_values t(:to_string)
|
68
|
-
# end
|
69
|
-
# transproc.call(a: 1, b: 2)
|
70
|
-
# # => {a: '1', b: '2'}
|
71
|
-
#
|
72
|
-
# @yield Block allowing to define transformations. The same as class level DSL
|
73
|
-
#
|
74
|
-
# @return [Function] Composed transproc
|
75
|
-
#
|
76
67
|
# @api public
|
77
|
-
def
|
78
|
-
|
68
|
+
def import(*args)
|
69
|
+
container.import(*args)
|
70
|
+
end
|
71
|
+
|
72
|
+
# @api public
|
73
|
+
def define!(&block)
|
74
|
+
@dsl ||= DSL.new(container)
|
75
|
+
@dsl.instance_eval(&block)
|
76
|
+
self
|
77
|
+
end
|
79
78
|
|
80
|
-
|
79
|
+
# @api public
|
80
|
+
def new(*args)
|
81
|
+
super(*args).tap do |transformer|
|
82
|
+
transformer.instance_variable_set('@transproc', dsl.(transformer)) if dsl
|
83
|
+
end
|
81
84
|
end
|
82
|
-
alias build define
|
83
85
|
|
84
86
|
# Get a transformation from the container,
|
85
87
|
# without adding it to the transformation pipeline
|
@@ -105,42 +107,6 @@ module Transproc
|
|
105
107
|
def t(fn, *args)
|
106
108
|
container[fn, *args]
|
107
109
|
end
|
108
|
-
|
109
|
-
# @api private
|
110
|
-
def method_missing(method, *args, &block)
|
111
|
-
if container.contain?(method)
|
112
|
-
args.push(define(&block)) if block_given?
|
113
|
-
transformations << t(method, *args)
|
114
|
-
else
|
115
|
-
super
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# @api private
|
120
|
-
def respond_to_missing?(method, _include_private = false)
|
121
|
-
container.contain?(method) || super
|
122
|
-
end
|
123
|
-
|
124
|
-
# @api private
|
125
|
-
def transproc
|
126
|
-
transformations.reduce(:>>)
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
|
131
|
-
# An array containing the transformation pipeline
|
132
|
-
#
|
133
|
-
# @api private
|
134
|
-
def transformations
|
135
|
-
@transformations ||= []
|
136
|
-
end
|
137
|
-
|
138
|
-
# @api private
|
139
|
-
def ensure_container_presence!
|
140
|
-
return if defined?(@container)
|
141
|
-
raise ArgumentError, 'Transformer function registry is empty. '\
|
142
|
-
'Provide your registry via Transproc::Transformer[YourRegistry]'
|
143
|
-
end
|
144
110
|
end
|
145
111
|
end
|
146
112
|
end
|