-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathregistry.rb
More file actions
150 lines (137 loc) · 3.93 KB
/
Copy pathregistry.rb
File metadata and controls
150 lines (137 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
module Dry
module Transformer
# Container to define transproc functions in, and access them via `[]` method
# from the outside of the module
#
# @example
# module FooMethods
# extend Dry::Transformer::Registry
#
# def self.foo(name, prefix)
# [prefix, '_', name].join
# end
# end
#
# fn = FooMethods[:foo, 'baz']
# fn['qux'] # => 'qux_baz'
#
# module BarMethods
# extend FooMethods
#
# def self.bar(*args)
# foo(*args).upcase
# end
# end
#
# fn = BarMethods[:foo, 'baz']
# fn['qux'] # => 'qux_baz'
#
# fn = BarMethods[:bar, 'baz']
# fn['qux'] # => 'QUX_BAZ'
#
# @api public
module Registry
# Builds the transformation
#
# @param [Proc, Symbol] fn
# A proc, a name of the module's own function, or a name of imported
# procedure from another module
# @param [Object, Array] args
# Args to be carried by the transproc
#
# @return [Dry::Transformer::Function]
#
# @alias :t
#
def [](fn, *args, **kwargs)
fetched = fetch(fn)
return Function.new(fetched, args: args, kwargs: kwargs, name: fn) unless already_wrapped?(fetched)
args.empty? ? fetched : fetched.with(*args)
end
alias_method :t, :[]
# Returns wether the registry contains such transformation by its key
#
# @param [Symbol] key
#
# @return [Boolean]
#
def contain?(key)
respond_to?(key) || store.contain?(key)
end
# Register a new function
#
# @example
# store.register(:to_json, -> v { v.to_json })
# store.register(:to_json) { |v| v.to_json }
#
def register(name, fn = nil, &block)
if contain?(name)
raise FunctionAlreadyRegisteredError, "Function #{name} is already defined"
end
@store = store.register(name, fn, &block)
self
end
# Imports either a method (converted to a proc) from another module, or
# all methods from that module.
#
# If the external module is a registry, looks for its imports too.
#
# @overload import(source)
# Loads all methods from the source object
#
# @param [Object] source
#
# @overload import(*names, **options)
# Loads selected methods from the source object
#
# @param [Array<Symbol>] names
# @param [Hash] options
# @options options [Object] :from The source object
#
# @overload import(name, **options)
# Loads selected methods from the source object
#
# @param [Symbol] name
# @param [Hash] options
# @options options [Object] :from The source object
# @options options [Object] :as The new name for the transformation
#
# @return [itself] self
#
# @alias :import
#
def import(*args)
@store = store.import(*args)
self
end
alias_method :uses, :import
# The store of procedures imported from external modules
#
# @return [Dry::Transformer::Store]
#
def store
@store ||= Store.new
end
# Gets the procedure for creating a transproc
#
# @param [#call, Symbol] fn
# Either the procedure, or the name of the method of the current module,
# or the registered key of imported procedure in a store.
#
# @return [#call]
#
def fetch(fn)
return fn unless fn.instance_of? Symbol
respond_to?(fn) ? method(fn) : store.fetch(fn)
rescue StandardError
raise FunctionNotFoundError.new(fn, self)
end
private
# @api private
def already_wrapped?(func)
func.is_a?(Dry::Transformer::Function) || func.is_a?(Dry::Transformer::Composite)
end
end
end
end