dry-transformer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +12 -0
- data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
- data/.github/ISSUE_TEMPLATE/---bug-report.md +30 -0
- data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
- data/.github/workflows/custom_ci.yml +66 -0
- data/.github/workflows/docsite.yml +34 -0
- data/.github/workflows/sync_configs.yml +34 -0
- data/.gitignore +16 -0
- data/.rspec +4 -0
- data/.rubocop.yml +95 -0
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +19 -0
- data/LICENSE +20 -0
- data/README.md +29 -0
- data/Rakefile +6 -0
- data/docsite/source/built-in-transformations.html.md +47 -0
- data/docsite/source/index.html.md +15 -0
- data/docsite/source/transformation-objects.html.md +32 -0
- data/docsite/source/using-standalone-functions.html.md +82 -0
- data/dry-transformer.gemspec +22 -0
- data/lib/dry-transformer.rb +3 -0
- data/lib/dry/transformer.rb +23 -0
- data/lib/dry/transformer/all.rb +11 -0
- data/lib/dry/transformer/array.rb +183 -0
- data/lib/dry/transformer/array/combine.rb +65 -0
- data/lib/dry/transformer/class.rb +56 -0
- data/lib/dry/transformer/coercions.rb +196 -0
- data/lib/dry/transformer/compiler.rb +47 -0
- data/lib/dry/transformer/composite.rb +54 -0
- data/lib/dry/transformer/conditional.rb +76 -0
- data/lib/dry/transformer/constants.rb +7 -0
- data/lib/dry/transformer/error.rb +16 -0
- data/lib/dry/transformer/function.rb +109 -0
- data/lib/dry/transformer/hash.rb +453 -0
- data/lib/dry/transformer/pipe.rb +75 -0
- data/lib/dry/transformer/pipe/class_interface.rb +115 -0
- data/lib/dry/transformer/pipe/dsl.rb +58 -0
- data/lib/dry/transformer/proc.rb +46 -0
- data/lib/dry/transformer/recursion.rb +121 -0
- data/lib/dry/transformer/registry.rb +150 -0
- data/lib/dry/transformer/store.rb +128 -0
- data/lib/dry/transformer/version.rb +7 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/array/combine_spec.rb +224 -0
- data/spec/unit/array_transformations_spec.rb +233 -0
- data/spec/unit/class_transformations_spec.rb +50 -0
- data/spec/unit/coercions_spec.rb +132 -0
- data/spec/unit/conditional_spec.rb +48 -0
- data/spec/unit/function_not_found_error_spec.rb +12 -0
- data/spec/unit/function_spec.rb +193 -0
- data/spec/unit/hash_transformations_spec.rb +490 -0
- data/spec/unit/proc_transformations_spec.rb +20 -0
- data/spec/unit/recursion_spec.rb +145 -0
- data/spec/unit/registry_spec.rb +202 -0
- data/spec/unit/store_spec.rb +198 -0
- data/spec/unit/transformer/class_interface_spec.rb +350 -0
- data/spec/unit/transformer/dsl_spec.rb +15 -0
- data/spec/unit/transformer/instance_methods_spec.rb +25 -0
- metadata +119 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transformer/pipe/class_interface'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Transformer
|
7
|
+
# Pipe class for defining transprocs with a class DSL.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# require 'anima'
|
11
|
+
# require 'dry/transformer/all'
|
12
|
+
#
|
13
|
+
# class User
|
14
|
+
# include Anima.new(:name, :address)
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class Address
|
18
|
+
# include Anima.new(:city, :street, :zipcode)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# class UsersMapper < Dry::Transformer::Pipe
|
22
|
+
# map_array do
|
23
|
+
# symbolize_keys
|
24
|
+
# rename_keys user_name: :name
|
25
|
+
# nest :address, %i(city street zipcode)
|
26
|
+
# map_value :address do
|
27
|
+
# constructor_inject Address
|
28
|
+
# end
|
29
|
+
# constructor_inject User
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# UsersMapper.new.call(
|
34
|
+
# [
|
35
|
+
# { 'user_name' => 'Jane',
|
36
|
+
# 'city' => 'NYC',
|
37
|
+
# 'street' => 'Street 1',
|
38
|
+
# 'zipcode' => '123'
|
39
|
+
# }
|
40
|
+
# ]
|
41
|
+
# )
|
42
|
+
# # => [
|
43
|
+
# #<User
|
44
|
+
# name="Jane"
|
45
|
+
# address=#<Address city="NYC" street="Street 1" zipcode="123">>
|
46
|
+
# ]
|
47
|
+
#
|
48
|
+
# @api public
|
49
|
+
class Pipe
|
50
|
+
extend ClassInterface
|
51
|
+
|
52
|
+
attr_reader :transproc
|
53
|
+
|
54
|
+
# Execute the transformation pipeline with the given input.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
#
|
58
|
+
# class SymbolizeKeys < Dry::Transformer
|
59
|
+
# symbolize_keys
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# SymbolizeKeys.new.call('name' => 'Jane')
|
63
|
+
# # => {:name=>"Jane"}
|
64
|
+
#
|
65
|
+
# @param [mixed] input The input to pass to the pipeline
|
66
|
+
#
|
67
|
+
# @return [mixed] output The output returned from the pipeline
|
68
|
+
#
|
69
|
+
# @api public
|
70
|
+
def call(input)
|
71
|
+
transproc.call(input)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transformer/pipe/dsl'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Transformer
|
7
|
+
class Pipe
|
8
|
+
# @api public
|
9
|
+
module ClassInterface
|
10
|
+
# @api private
|
11
|
+
attr_reader :dsl
|
12
|
+
|
13
|
+
# Return a base Dry::Transformer class with the
|
14
|
+
# container configured to the passed argument.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
#
|
18
|
+
# class MyTransformer < Dry::Transformer[Transproc]
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @param [Transproc::Registry] container
|
22
|
+
# The container to resolve transprocs from
|
23
|
+
#
|
24
|
+
# @return [subclass of Dry::Transformer]
|
25
|
+
#
|
26
|
+
# @api public
|
27
|
+
def [](container)
|
28
|
+
klass = Class.new(self)
|
29
|
+
klass.container(container)
|
30
|
+
klass
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
def inherited(subclass)
|
35
|
+
super
|
36
|
+
|
37
|
+
subclass.container(@container) if defined?(@container)
|
38
|
+
|
39
|
+
subclass.instance_variable_set('@dsl', dsl.dup) if dsl
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get or set the container to resolve transprocs from.
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
#
|
46
|
+
# # Setter
|
47
|
+
# Dry::Transformer.container(Transproc)
|
48
|
+
# # => Transproc
|
49
|
+
#
|
50
|
+
# # Getter
|
51
|
+
# Dry::Transformer.container
|
52
|
+
# # => Transproc
|
53
|
+
#
|
54
|
+
# @param [Transproc::Registry] container
|
55
|
+
# The container to resolve transprocs from
|
56
|
+
#
|
57
|
+
# @return [Transproc::Registry]
|
58
|
+
#
|
59
|
+
# @api private
|
60
|
+
def container(container = Undefined)
|
61
|
+
if container.equal?(Undefined)
|
62
|
+
@container ||= Module.new.extend(Dry::Transformer::Registry)
|
63
|
+
else
|
64
|
+
@container = container
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api public
|
69
|
+
def import(*args)
|
70
|
+
container.import(*args)
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api public
|
74
|
+
def define!(&block)
|
75
|
+
@dsl ||= DSL.new(container)
|
76
|
+
@dsl.instance_eval(&block)
|
77
|
+
self
|
78
|
+
end
|
79
|
+
|
80
|
+
# @api public
|
81
|
+
def new(*)
|
82
|
+
super.tap do |transformer|
|
83
|
+
transformer.instance_variable_set('@transproc', dsl.(transformer)) if dsl
|
84
|
+
end
|
85
|
+
end
|
86
|
+
ruby2_keywords(:new) if respond_to?(:ruby2_keywords, true)
|
87
|
+
|
88
|
+
# Get a transformation from the container,
|
89
|
+
# without adding it to the transformation pipeline
|
90
|
+
#
|
91
|
+
# @example
|
92
|
+
#
|
93
|
+
# class Stringify < Dry::Transformer
|
94
|
+
# map_values t(:to_string)
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# Stringify.new.call(a: 1, b: 2)
|
98
|
+
# # => {a: '1', b: '2'}
|
99
|
+
#
|
100
|
+
# @param [Proc, Symbol] fn
|
101
|
+
# A proc, a name of the module's own function, or a name of imported
|
102
|
+
# procedure from another module
|
103
|
+
# @param [Object, Array] args
|
104
|
+
# Args to be carried by the transproc
|
105
|
+
#
|
106
|
+
# @return [Transproc::Function]
|
107
|
+
#
|
108
|
+
# @api public
|
109
|
+
def t(fn, *args)
|
110
|
+
container[fn, *args]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transformer/compiler'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Transformer
|
7
|
+
class Pipe
|
8
|
+
# @api public
|
9
|
+
class DSL
|
10
|
+
# @api private
|
11
|
+
attr_reader :container
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
attr_reader :ast
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
def initialize(container, ast: [], &block)
|
18
|
+
@container = container
|
19
|
+
@ast = ast
|
20
|
+
instance_eval(&block) if block
|
21
|
+
end
|
22
|
+
|
23
|
+
# @api public
|
24
|
+
def t(name, *args)
|
25
|
+
container[name, *args]
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
def dup
|
30
|
+
self.class.new(container, ast: ast.dup)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @api private
|
34
|
+
def call(transformer)
|
35
|
+
Compiler.new(container, transformer).(ast)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @api private
|
41
|
+
def node(&block)
|
42
|
+
[:t, self.class.new(container, &block).ast]
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api private
|
46
|
+
def respond_to_missing?(method, _include_private = false)
|
47
|
+
super || container.contain?(method)
|
48
|
+
end
|
49
|
+
|
50
|
+
# @api private
|
51
|
+
def method_missing(meth, *args, &block)
|
52
|
+
arg_nodes = *args.map { |a| [:arg, a] }
|
53
|
+
ast << [:fn, (block ? [meth, [*arg_nodes, node(&block)]] : [meth, arg_nodes])]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Transformer
|
5
|
+
# Transformation functions for Procs
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# require 'ostruct'
|
9
|
+
# require 'dry/transformer/proc'
|
10
|
+
#
|
11
|
+
# include Dry::Transformer::Helper
|
12
|
+
#
|
13
|
+
# fn = t(
|
14
|
+
# :map_value,
|
15
|
+
# 'foo_bar',
|
16
|
+
# t(:bind, OpenStruct.new(prefix: 'foo'), -> s { [prefix, s].join('_') })
|
17
|
+
# )
|
18
|
+
#
|
19
|
+
# fn["foo_bar" => "bar"]
|
20
|
+
# # => {"foo_bar" => "foo_bar"}
|
21
|
+
#
|
22
|
+
# @api public
|
23
|
+
module ProcTransformations
|
24
|
+
extend Registry
|
25
|
+
|
26
|
+
# Change the binding for the given function
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# Dry::Transformer(
|
30
|
+
# :bind,
|
31
|
+
# OpenStruct.new(prefix: 'foo'),
|
32
|
+
# -> s { [prefix, s].join('_') }
|
33
|
+
# )['bar']
|
34
|
+
# # => "foo_bar"
|
35
|
+
#
|
36
|
+
# @param [Proc]
|
37
|
+
#
|
38
|
+
# @return [Proc]
|
39
|
+
#
|
40
|
+
# @api public
|
41
|
+
def self.bind(value, binding, fn)
|
42
|
+
binding.instance_exec(value, &fn)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/transformer/conditional'
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
module Transformer
|
7
|
+
# Recursive transformation functions
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# require 'dry/transformer/recursion'
|
11
|
+
#
|
12
|
+
# include Dry::Transformer::Helper
|
13
|
+
#
|
14
|
+
# fn = t(:hash_recursion, t(:symbolize_keys))
|
15
|
+
#
|
16
|
+
# fn["name" => "Jane", "address" => { "street" => "Street 1" }]
|
17
|
+
# # => {:name=>"Jane", :address=>{:street=>"Street 1"}}
|
18
|
+
#
|
19
|
+
# @api public
|
20
|
+
module Recursion
|
21
|
+
extend Registry
|
22
|
+
|
23
|
+
IF_ENUMERABLE = -> fn { Conditional[:is, Enumerable, fn] }
|
24
|
+
|
25
|
+
IF_ARRAY = -> fn { Conditional[:is, Array, fn] }
|
26
|
+
|
27
|
+
IF_HASH = -> fn { Conditional[:is, Hash, fn] }
|
28
|
+
|
29
|
+
# Recursively apply the provided transformation function to an enumerable
|
30
|
+
#
|
31
|
+
# @example
|
32
|
+
# Dry::Transformer(:recursion, Dry::Transformer(:is, ::Hash, Dry::Transformer(:symbolize_keys)))[
|
33
|
+
# {
|
34
|
+
# 'id' => 1,
|
35
|
+
# 'name' => 'Jane',
|
36
|
+
# 'tasks' => [
|
37
|
+
# { 'id' => 1, 'description' => 'Write some code' },
|
38
|
+
# { 'id' => 2, 'description' => 'Write some more code' }
|
39
|
+
# ]
|
40
|
+
# }
|
41
|
+
# ]
|
42
|
+
# => {
|
43
|
+
# :id=>1,
|
44
|
+
# :name=>"Jane",
|
45
|
+
# :tasks=>[
|
46
|
+
# {:id=>1, :description=>"Write some code"},
|
47
|
+
# {:id=>2, :description=>"Write some more code"}
|
48
|
+
# ]
|
49
|
+
# }
|
50
|
+
#
|
51
|
+
# @param [Enumerable]
|
52
|
+
#
|
53
|
+
# @return [Enumerable]
|
54
|
+
#
|
55
|
+
# @api public
|
56
|
+
def self.recursion(value, fn)
|
57
|
+
result = fn[value]
|
58
|
+
guarded = IF_ENUMERABLE[-> v { recursion(v, fn) }]
|
59
|
+
|
60
|
+
case result
|
61
|
+
when ::Hash
|
62
|
+
result.keys.each do |key|
|
63
|
+
result[key] = guarded[result.delete(key)]
|
64
|
+
end
|
65
|
+
when ::Array
|
66
|
+
result.map! do |item|
|
67
|
+
guarded[item]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
# Recursively apply the provided transformation function to an array
|
75
|
+
#
|
76
|
+
# @example
|
77
|
+
# Dry::Transformer(:array_recursion, -> s { s.compact })[
|
78
|
+
# [['Joe', 'Jane', nil], ['Smith', 'Doe', nil]]
|
79
|
+
# ]
|
80
|
+
# # => [["Joe", "Jane"], ["Smith", "Doe"]]
|
81
|
+
#
|
82
|
+
# @param [Array]
|
83
|
+
#
|
84
|
+
# @return [Array]
|
85
|
+
#
|
86
|
+
# @api public
|
87
|
+
def self.array_recursion(value, fn)
|
88
|
+
result = fn[value]
|
89
|
+
guarded = IF_ARRAY[-> v { array_recursion(v, fn) }]
|
90
|
+
|
91
|
+
result.map! do |item|
|
92
|
+
guarded[item]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Recursively apply the provided transformation function to a hash
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
# Dry::Transformer(:hash_recursion, Dry::Transformer(:symbolize_keys))[
|
100
|
+
# ["name" => "Jane", "address" => { "street" => "Street 1", "zipcode" => "123" }]
|
101
|
+
# ]
|
102
|
+
# # => {:name=>"Jane", :address=>{:street=>"Street 1", :zipcode=>"123"}}
|
103
|
+
#
|
104
|
+
# @param [Hash]
|
105
|
+
#
|
106
|
+
# @return [Hash]
|
107
|
+
#
|
108
|
+
# @api public
|
109
|
+
def self.hash_recursion(value, fn)
|
110
|
+
result = fn[value]
|
111
|
+
guarded = IF_HASH[-> v { hash_recursion(v, fn) }]
|
112
|
+
|
113
|
+
result.keys.each do |key|
|
114
|
+
result[key] = guarded[result.delete(key)]
|
115
|
+
end
|
116
|
+
|
117
|
+
result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dry
|
4
|
+
module Transformer
|
5
|
+
# Container to define transproc functions in, and access them via `[]` method
|
6
|
+
# from the outside of the module
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# module FooMethods
|
10
|
+
# extend Dry::Transformer::Registry
|
11
|
+
#
|
12
|
+
# def self.foo(name, prefix)
|
13
|
+
# [prefix, '_', name].join
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# fn = FooMethods[:foo, 'baz']
|
18
|
+
# fn['qux'] # => 'qux_baz'
|
19
|
+
#
|
20
|
+
# module BarMethods
|
21
|
+
# extend FooMethods
|
22
|
+
#
|
23
|
+
# def self.bar(*args)
|
24
|
+
# foo(*args).upcase
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# fn = BarMethods[:foo, 'baz']
|
29
|
+
# fn['qux'] # => 'qux_baz'
|
30
|
+
#
|
31
|
+
# fn = BarMethods[:bar, 'baz']
|
32
|
+
# fn['qux'] # => 'QUX_BAZ'
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
module Registry
|
36
|
+
# Builds the transformation
|
37
|
+
#
|
38
|
+
# @param [Proc, Symbol] fn
|
39
|
+
# A proc, a name of the module's own function, or a name of imported
|
40
|
+
# procedure from another module
|
41
|
+
# @param [Object, Array] args
|
42
|
+
# Args to be carried by the transproc
|
43
|
+
#
|
44
|
+
# @return [Dry::Transformer::Function]
|
45
|
+
#
|
46
|
+
# @alias :t
|
47
|
+
#
|
48
|
+
def [](fn, *args)
|
49
|
+
fetched = fetch(fn)
|
50
|
+
|
51
|
+
return Function.new(fetched, args: args, name: fn) unless already_wrapped?(fetched)
|
52
|
+
|
53
|
+
args.empty? ? fetched : fetched.with(*args)
|
54
|
+
end
|
55
|
+
alias_method :t, :[]
|
56
|
+
|
57
|
+
# Returns wether the registry contains such transformation by its key
|
58
|
+
#
|
59
|
+
# @param [Symbol] key
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
#
|
63
|
+
def contain?(key)
|
64
|
+
respond_to?(key) || store.contain?(key)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Register a new function
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# store.register(:to_json, -> v { v.to_json })
|
71
|
+
|
72
|
+
# store.register(:to_json) { |v| v.to_json }
|
73
|
+
#
|
74
|
+
def register(name, fn = nil, &block)
|
75
|
+
if contain?(name)
|
76
|
+
raise FunctionAlreadyRegisteredError, "Function #{name} is already defined"
|
77
|
+
end
|
78
|
+
|
79
|
+
@store = store.register(name, fn, &block)
|
80
|
+
self
|
81
|
+
end
|
82
|
+
|
83
|
+
# Imports either a method (converted to a proc) from another module, or
|
84
|
+
# all methods from that module.
|
85
|
+
#
|
86
|
+
# If the external module is a registry, looks for its imports too.
|
87
|
+
#
|
88
|
+
# @overload import(source)
|
89
|
+
# Loads all methods from the source object
|
90
|
+
#
|
91
|
+
# @param [Object] source
|
92
|
+
#
|
93
|
+
# @overload import(*names, **options)
|
94
|
+
# Loads selected methods from the source object
|
95
|
+
#
|
96
|
+
# @param [Array<Symbol>] names
|
97
|
+
# @param [Hash] options
|
98
|
+
# @options options [Object] :from The source object
|
99
|
+
#
|
100
|
+
# @overload import(name, **options)
|
101
|
+
# Loads selected methods from the source object
|
102
|
+
#
|
103
|
+
# @param [Symbol] name
|
104
|
+
# @param [Hash] options
|
105
|
+
# @options options [Object] :from The source object
|
106
|
+
# @options options [Object] :as The new name for the transformation
|
107
|
+
#
|
108
|
+
# @return [itself] self
|
109
|
+
#
|
110
|
+
# @alias :import
|
111
|
+
#
|
112
|
+
def import(*args)
|
113
|
+
@store = store.import(*args)
|
114
|
+
self
|
115
|
+
end
|
116
|
+
alias_method :uses, :import
|
117
|
+
|
118
|
+
# The store of procedures imported from external modules
|
119
|
+
#
|
120
|
+
# @return [Dry::Transformer::Store]
|
121
|
+
#
|
122
|
+
def store
|
123
|
+
@store ||= Store.new
|
124
|
+
end
|
125
|
+
|
126
|
+
# Gets the procedure for creating a transproc
|
127
|
+
#
|
128
|
+
# @param [#call, Symbol] fn
|
129
|
+
# Either the procedure, or the name of the method of the current module,
|
130
|
+
# or the registered key of imported procedure in a store.
|
131
|
+
#
|
132
|
+
# @return [#call]
|
133
|
+
#
|
134
|
+
def fetch(fn)
|
135
|
+
return fn unless fn.instance_of? Symbol
|
136
|
+
|
137
|
+
respond_to?(fn) ? method(fn) : store.fetch(fn)
|
138
|
+
rescue StandardError
|
139
|
+
raise FunctionNotFoundError.new(fn, self)
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# @api private
|
145
|
+
def already_wrapped?(func)
|
146
|
+
func.is_a?(Dry::Transformer::Function) || func.is_a?(Dry::Transformer::Composite)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|