remap 2.0.2 → 2.1.5

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/remap/base.rb +229 -75
  3. data/lib/remap/compiler.rb +403 -37
  4. data/lib/remap/constructor/argument.rb +20 -6
  5. data/lib/remap/constructor/keyword.rb +20 -4
  6. data/lib/remap/constructor/none.rb +3 -4
  7. data/lib/remap/constructor.rb +12 -5
  8. data/lib/remap/contract.rb +27 -0
  9. data/lib/remap/extensions/enumerable.rb +48 -0
  10. data/lib/remap/extensions/hash.rb +13 -0
  11. data/lib/remap/extensions/object.rb +37 -0
  12. data/lib/remap/failure.rb +25 -15
  13. data/lib/remap/iteration/array.rb +20 -11
  14. data/lib/remap/iteration/hash.rb +21 -13
  15. data/lib/remap/iteration/other.rb +7 -7
  16. data/lib/remap/iteration.rb +8 -2
  17. data/lib/remap/mapper/and.rb +29 -7
  18. data/lib/remap/mapper/binary.rb +3 -6
  19. data/lib/remap/mapper/or.rb +29 -6
  20. data/lib/remap/mapper/support/operations.rb +40 -0
  21. data/lib/remap/mapper/xor.rb +29 -7
  22. data/lib/remap/mapper.rb +1 -48
  23. data/lib/remap/notice/traced.rb +19 -0
  24. data/lib/remap/notice/untraced.rb +11 -0
  25. data/lib/remap/notice.rb +34 -0
  26. data/lib/remap/operation.rb +26 -13
  27. data/lib/remap/path/input.rb +37 -0
  28. data/lib/remap/path/output.rb +26 -0
  29. data/lib/remap/path.rb +22 -0
  30. data/lib/remap/path_error.rb +13 -0
  31. data/lib/remap/proxy.rb +18 -0
  32. data/lib/remap/rule/each.rb +25 -24
  33. data/lib/remap/rule/embed.rb +33 -28
  34. data/lib/remap/rule/map/optional.rb +42 -0
  35. data/lib/remap/rule/map/required.rb +35 -0
  36. data/lib/remap/rule/map.rb +176 -55
  37. data/lib/remap/rule/set.rb +23 -33
  38. data/lib/remap/rule/support/collection/empty.rb +7 -7
  39. data/lib/remap/rule/support/collection/filled.rb +21 -8
  40. data/lib/remap/rule/support/collection.rb +11 -3
  41. data/lib/remap/rule/support/enum.rb +44 -21
  42. data/lib/remap/rule/void.rb +17 -18
  43. data/lib/remap/rule/wrap.rb +25 -17
  44. data/lib/remap/rule.rb +8 -1
  45. data/lib/remap/selector/all.rb +29 -7
  46. data/lib/remap/selector/index.rb +24 -16
  47. data/lib/remap/selector/key.rb +31 -16
  48. data/lib/remap/selector.rb +17 -0
  49. data/lib/remap/state/extension.rb +182 -208
  50. data/lib/remap/state/schema.rb +1 -1
  51. data/lib/remap/state.rb +30 -4
  52. data/lib/remap/static/fixed.rb +14 -3
  53. data/lib/remap/static/option.rb +21 -6
  54. data/lib/remap/static.rb +13 -0
  55. data/lib/remap/struct.rb +1 -0
  56. data/lib/remap/types.rb +13 -28
  57. data/lib/remap.rb +15 -19
  58. metadata +95 -93
  59. data/lib/remap/result.rb +0 -11
  60. data/lib/remap/rule/support/path.rb +0 -45
  61. data/lib/remap/state/types.rb +0 -11
  62. data/lib/remap/success.rb +0 -29
  63. data/lib/remap/version.rb +0 -5
@@ -1,17 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Remap
4
- class Compiler
5
- include Dry::Core::Constants
6
- extend Dry::Initializer
7
- extend Forwardable
8
-
9
- param :rules, default: -> { EMPTY_ARRAY.dup }
4
+ # Constructs a {Rule} from the block passed to {Remap::Base.define}
5
+ class Compiler < Proxy
6
+ # @return [Array<Rule>]
7
+ param :rules, type: Types.Array(Rule)
10
8
 
11
9
  # @return [Rule]
12
- delegate call: self
10
+ delegate :call, to: Compiler
13
11
 
14
- # Constructs a rule tree given {block}
12
+ # Constructs a rule tree given block
13
+ #
14
+ # @example Compiles two rules, [get] and [map]
15
+ # rule = Remap::Compiler.call do
16
+ # get :name
17
+ # get :age
18
+ # end
19
+ #
20
+ # state = Remap::State.call({
21
+ # name: "John",
22
+ # age: 50
23
+ # })
24
+ #
25
+ # error = -> failure { raise failure.exception }
26
+ #
27
+ # rule.call(state, &error).fetch(:value) # => { name: "John", age: 50 }
15
28
  #
16
29
  # @return [Rule]
17
30
  def self.call(&block)
@@ -19,83 +32,324 @@ module Remap
19
32
  return Rule::Void.new
20
33
  end
21
34
 
22
- new.tap { _1.instance_eval(&block) }.rule
35
+ new([]).tap do |compiler|
36
+ compiler.instance_exec(&block)
37
+ end.rule
23
38
  end
24
39
 
25
- # Maps {path} to {to} with {block} inbetween
40
+ # Maps input path [input] to output path [to]
26
41
  #
27
42
  # @param path ([]) [Array<Segment>, Segment]
28
43
  # @param to ([]) [Array<Symbol>, Symbol]
29
44
  #
30
- # @return [Rule::Map]
31
- def map(*path, to: EMPTY_ARRAY, &block)
32
- add Rule::Map.new(
45
+ # @example From path [:name] to [:nickname]
46
+ # rule = Remap::Compiler.call do
47
+ # map :name, to: :nickname
48
+ # end
49
+ #
50
+ # state = Remap::State.call({
51
+ # name: "John"
52
+ # })
53
+ #
54
+ # output = rule.call(state) do |failure|
55
+ # raise failure.exception
56
+ # end
57
+ #
58
+ # output.fetch(:value) # => { nickname: "John" }
59
+ #
60
+ # @return [Rule::Map::Required]
61
+ def map(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
62
+ add Rule::Map::Required.call(
63
+ path: {
64
+ output: [to].flatten,
65
+ input: path.flatten
66
+ },
67
+ backtrace: backtrace,
68
+ rule: call(&block))
69
+ end
70
+
71
+ # Optional version of {#map}
72
+ #
73
+ # @example Map an optional field
74
+ # rule = Remap::Compiler.call do
75
+ # to :person do
76
+ # map? :age, to: :age
77
+ # map :name, to: :name
78
+ # end
79
+ # end
80
+ #
81
+ # state = Remap::State.call({
82
+ # name: "John"
83
+ # })
84
+ #
85
+ # output = rule.call(state) do |failure|
86
+ # raise failure.exception
87
+ # end
88
+ #
89
+ # output.fetch(:value) # => { person: { name: "John" } }
90
+ #
91
+ # @see #map
92
+ #
93
+ # @return [Rule::Map::Optional]
94
+ def map?(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
95
+ add Rule::Map::Optional.call(
33
96
  path: {
34
- map: path.flatten,
35
- to: [to].flatten
97
+ output: [to].flatten,
98
+ input: path.flatten
36
99
  },
37
- rule: call(&block)
38
- )
100
+ backtrace: backtrace,
101
+ rule: call(&block))
39
102
  end
40
103
 
41
- # Maps using {mapper}
104
+ # Select a path and uses the same path as output
105
+ #
106
+ # @param path ([]) [Array<Segment>, Segment]
107
+ #
108
+ # @example Map from [:name] to [:name]
109
+ # rule = Remap::Compiler.call do
110
+ # get :name
111
+ # end
112
+ #
113
+ # state = Remap::State.call({
114
+ # name: "John"
115
+ # })
116
+ #
117
+ # output = rule.call(state) do |failure|
118
+ # raise failure.exception
119
+ # end
120
+ #
121
+ # output.fetch(:value) # => { name: "John" }
122
+ #
123
+ # @return [Rule::Map::Required]
124
+ def get(*path, backtrace: Kernel.caller, &block)
125
+ map(path, to: path, backtrace: backtrace, &block)
126
+ end
127
+
128
+ # Optional version of {#get}
129
+ #
130
+ # @example Map from [:name] to [:name]
131
+ # rule = Remap::Compiler.call do
132
+ # get :name
133
+ # get? :age
134
+ # end
135
+ #
136
+ # state = Remap::State.call({
137
+ # name: "John"
138
+ # })
139
+ #
140
+ # output = rule.call(state) do |failure|
141
+ # raise failure.exception
142
+ # end
143
+ #
144
+ # output.fetch(:value) # => { name: "John" }
145
+ #
146
+ # @see #get
147
+ #
148
+ # @return [Rule::Map::Optional]
149
+ def get?(*path, backtrace: Kernel.caller, &block)
150
+ map?(path, to: path, backtrace: backtrace, &block)
151
+ end
152
+
153
+ # Maps using mapper
42
154
  #
43
155
  # @param mapper [Remap]
44
156
  #
157
+ # @example Embed mapper Car into a person
158
+ # class Car < Remap::Base
159
+ # define do
160
+ # map :car do
161
+ # map :name, to: :car
162
+ # end
163
+ # end
164
+ # end
165
+ #
166
+ # rule = Remap::Compiler.call do
167
+ # map :person do
168
+ # embed Car
169
+ # end
170
+ # end
171
+ #
172
+ # state = Remap::State.call({
173
+ # person: {
174
+ # car: {
175
+ # name: "Volvo"
176
+ # }
177
+ # }
178
+ # })
179
+ #
180
+ # output = rule.call(state) do |failure|
181
+ # raise failure.exception
182
+ # end
183
+ #
184
+ # output.fetch(:value) # => { car: "Volvo" }
185
+ #
45
186
  # @return [Rule::Embed]
46
- def embed(mapper)
187
+ def embed(mapper, &block)
188
+ if block
189
+ raise ArgumentError, "#embed does not take a block"
190
+ end
191
+
47
192
  add Rule::Embed.new(mapper: mapper)
48
193
  rescue Dry::Struct::Error
49
194
  raise ArgumentError, "Embeded mapper must be [Remap::Mapper], got [#{mapper}]"
50
195
  end
51
196
 
52
- # @param *path ([]) [Symbol, Array<Symbol>]
197
+ # Set a static value
198
+ #
199
+ # @param path ([]) [Symbol, Array<Symbol>]
53
200
  # @option to [Remap::Static]
54
201
  #
202
+ # @example Set static value to { name: "John" }
203
+ # rule = Remap::Compiler.call do
204
+ # set :name, to: value("John")
205
+ # end
206
+ #
207
+ # state = Remap::State.call({})
208
+ #
209
+ # output = rule.call(state) do |failure|
210
+ # raise failure.exception
211
+ # end
212
+ #
213
+ # output.fetch(:value) # => { name: "John" }
214
+ #
215
+ # @example Reference an option
216
+ # rule = Remap::Compiler.call do
217
+ # set :name, to: option(:name)
218
+ # end
219
+ #
220
+ # state = Remap::State.call({}, options: { name: "John" })
221
+ #
222
+ # output = rule.call(state) do |failure|
223
+ # raise failure.exception
224
+ # end
225
+ #
226
+ # output.fetch(:value) # => { name: "John" }
227
+ #
55
228
  # @return [Rule::Set]
56
229
  # @raise [ArgumentError]
57
230
  # if no path given
58
231
  # if path is not a Symbol or Array<Symbol>
59
- def set(*path, to:)
60
- add Rule::Set.new(path: { to: path.flatten, map: EMPTY_ARRAY }, value: to)
232
+ def set(*path, to:, &block)
233
+ if block
234
+ raise ArgumentError, "#set does not take a block"
235
+ end
236
+
237
+ add Rule::Set.new(path: path.flatten, value: to)
61
238
  rescue Dry::Struct::Error => e
62
239
  raise ArgumentError, e.message
63
240
  end
64
241
 
65
- # Maps to {path} from {map} with {block} inbetween
242
+ # Maps to path from map with block in between
66
243
  #
67
244
  # @param path [Array<Symbol>, Symbol]
68
245
  # @param map [Array<Segment>, Segment]
69
246
  #
247
+ # @example From path [:name] to [:nickname]
248
+ # rule = Remap::Compiler.call do
249
+ # to :nickname, map: :name
250
+ # end
251
+ #
252
+ # state = Remap::State.call({
253
+ # name: "John"
254
+ # })
255
+ #
256
+ # output = rule.call(state) do |failure|
257
+ # raise failure.exception
258
+ # end
259
+ #
260
+ # output.fetch(:value) # => { nickname: "John" }
261
+ #
70
262
  # @return [Rule::Map]
71
- def to(*path, map: EMPTY_ARRAY, &block)
72
- map(*map, to: path, &block)
263
+ def to(*path, map: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
264
+ map(*map, to: path, backtrace: backtrace, &block)
265
+ end
266
+
267
+ # Optional version of {#to}
268
+ #
269
+ # @example Map an optional field
270
+ # rule = Remap::Compiler.call do
271
+ # to :person do
272
+ # to? :age, map: :age
273
+ # to :name, map: :name
274
+ # end
275
+ # end
276
+ #
277
+ # state = Remap::State.call({
278
+ # name: "John"
279
+ # })
280
+ #
281
+ # output = rule.call(state) do |failure|
282
+ # raise failure.exception
283
+ # end
284
+ #
285
+ # output.fetch(:value) # => { person: { name: "John" } }
286
+ # @see #to
287
+ #
288
+ # @return [Rule::Map::Optional]
289
+ def to?(*path, map: EMPTY_ARRAY, &block)
290
+ map?(*map, to: path, &block)
73
291
  end
74
292
 
75
293
  # Iterates over the input value, passes each value
76
294
  # to its block and merges the result back together
77
295
  #
296
+ # @example Map an array of hashes
297
+ # rule = Remap::Compiler.call do
298
+ # each do
299
+ # map :name
300
+ # end
301
+ # end
302
+ #
303
+ # state = Remap::State.call([{
304
+ # name: "John"
305
+ # }, {
306
+ # name: "Jane"
307
+ # }])
308
+ #
309
+ # output = rule.call(state) do |failure|
310
+ # raise failure.exception
311
+ # end
312
+ #
313
+ # output.fetch(:value) # => ["John", "Jane"]
314
+ #
78
315
  # @return [Rule::Each]]
79
316
  # @raise [ArgumentError] if no block given
80
317
  def each(&block)
81
318
  unless block
82
- raise ArgumentError, "no block given"
319
+ raise ArgumentError, "#each requires a block"
83
320
  end
84
321
 
85
322
  add Rule::Each.new(rule: call(&block))
86
323
  end
87
324
 
88
- # Wraps output in {type}
325
+ # Wraps output in type
89
326
  #
90
327
  # @param type [:array]
91
328
  #
92
329
  # @yieldreturn [Rule]
93
330
  #
331
+ # @example Wrap an output value in an array
332
+ # rule = Remap::Compiler.call do
333
+ # wrap(:array) do
334
+ # map :name
335
+ # end
336
+ # end
337
+ #
338
+ # state = Remap::State.call({
339
+ # name: "John"
340
+ # })
341
+ #
342
+ # output = rule.call(state) do |failure|
343
+ # raise failure.exception
344
+ # end
345
+ #
346
+ # output.fetch(:value) # => ["John"]
347
+ #
94
348
  # @return [Rule::Wrap]
95
349
  # @raise [ArgumentError] if type is not :array
96
350
  def wrap(type, &block)
97
351
  unless block
98
- raise ArgumentError, "no block given"
352
+ raise ArgumentError, "#wrap requires a block"
99
353
  end
100
354
 
101
355
  add Rule::Wrap.new(type: type, rule: call(&block))
@@ -105,8 +359,28 @@ module Remap
105
359
 
106
360
  # Selects all elements
107
361
  #
362
+ # @example Select all keys in array
363
+ # rule = Remap::Compiler.call do
364
+ # map all, :name, to: :names
365
+ # end
366
+ #
367
+ # state = Remap::State.call([
368
+ # { name: "John" },
369
+ # { name: "Jane" }
370
+ # ])
371
+ #
372
+ # output = rule.call(state) do |failure|
373
+ # raise failure.exception
374
+ # end
375
+ #
376
+ # output.fetch(:value) # => { names: ["John", "Jane"] }
377
+ #
108
378
  # @return [Rule::Path::Segment::Quantifier::All]
109
- def all
379
+ def all(&block)
380
+ if block
381
+ raise ArgumentError, "all selector does not take a block"
382
+ end
383
+
110
384
  Selector::All.new(EMPTY_HASH)
111
385
  end
112
386
 
@@ -114,44 +388,136 @@ module Remap
114
388
  #
115
389
  # @param value [Any]
116
390
  #
391
+ # @example Set path to static value
392
+ # rule = Remap::Compiler.call do
393
+ # set :api_key, to: value("<SECRET>")
394
+ # end
395
+ #
396
+ # state = Remap::State.call({})
397
+ #
398
+ # output = rule.call(state) do |failure|
399
+ # raise failure.exception
400
+ # end
401
+ #
402
+ # output.fetch(:value) # => { api_key: "<SECRET>" }
403
+ #
117
404
  # @return [Rule::Static::Fixed]
118
- def value(value)
405
+ def value(value, &block)
406
+ if block
407
+ raise ArgumentError, "option selector does not take a block"
408
+ end
409
+
119
410
  Static::Fixed.new(value: value)
120
411
  end
121
412
 
122
413
  # Static option to be selected
123
414
  #
415
+ # @example Set path to option
416
+ # rule = Remap::Compiler.call do
417
+ # set :meaning_of_life, to: option(:number)
418
+ # end
419
+ #
420
+ # state = Remap::State.call({}, options: { number: 42 })
421
+ #
422
+ # output = rule.call(state) do |failure|
423
+ # raise failure.exception
424
+ # end
425
+ #
426
+ # output.fetch(:value) # => { meaning_of_life: 42 }
427
+ #
124
428
  # @param id [Symbol]
125
429
  #
126
430
  # @return [Rule::Static::Option]
127
- def option(id)
128
- Static::Option.new(name: id)
431
+ def option(id, backtrace: Kernel.caller, &block)
432
+ if block
433
+ raise ArgumentError, "option selector does not take a block"
434
+ end
435
+
436
+ Static::Option.new(name: id, backtrace: backtrace)
129
437
  end
130
438
 
131
- # Selects {index} element in input
439
+ # Selects index element in input
132
440
  #
133
441
  # @param index [Integer]
134
442
  #
443
+ # @example Select value at index
444
+ # rule = Remap::Compiler.call do
445
+ # map :names, at(1), to: :name
446
+ # end
447
+ #
448
+ # state = Remap::State.call({
449
+ # names: ["John", "Jane"]
450
+ # })
451
+ #
452
+ # output = rule.call(state) do |failure|
453
+ # raise failure.exception
454
+ # end
455
+ #
456
+ # output.fetch(:value) # => { name: "Jane" }
457
+ #
135
458
  # @return [Path::Segment::Key]
136
459
  # @raise [ArgumentError] if index is not an Integer
137
- def at(index)
460
+ def at(index, &block)
461
+ if block
462
+ raise ArgumentError, "first selector does not take a block"
463
+ end
464
+
138
465
  Selector::Index.new(index: index)
139
466
  rescue Dry::Struct::Error
140
- raise ArgumentError, "Selector at(index) requires an integer argument, got [#{index}] (#{index.class})"
467
+ raise ArgumentError,
468
+ "Selector at(index) requires an integer argument, got [#{index}] (#{index.class})"
141
469
  end
142
470
 
143
471
  # Selects first element in input
144
472
  #
473
+ # @example Select first value in an array
474
+ # rule = Remap::Compiler.call do
475
+ # map :names, first, to: :name
476
+ # end
477
+ #
478
+ # state = Remap::State.call({
479
+ # names: ["John", "Jane"]
480
+ # })
481
+ #
482
+ # output = rule.call(state) do |failure|
483
+ # raise failure.exception
484
+ # end
485
+ #
486
+ # output.fetch(:value) # => { name: "John" }
487
+ #
145
488
  # @return [Path::Segment::Key]]
146
- def first
489
+ def first(&block)
490
+ if block
491
+ raise ArgumentError, "first selector does not take a block"
492
+ end
493
+
147
494
  at(0)
148
495
  end
149
496
  alias any first
150
497
 
151
498
  # Selects last element in input
152
499
  #
500
+ # @example Select last value in an array
501
+ # rule = Remap::Compiler.call do
502
+ # map :names, last, to: :name
503
+ # end
504
+ #
505
+ # state = Remap::State.call({
506
+ # names: ["John", "Jane", "Linus"]
507
+ # })
508
+ #
509
+ # output = rule.call(state) do |failure|
510
+ # raise failure.exception
511
+ # end
512
+ #
513
+ # output.fetch(:value) # => { name: "Linus" }
514
+ #
153
515
  # @return [Path::Segment::Key]
154
- def last
516
+ def last(&block)
517
+ if block
518
+ raise ArgumentError, "last selector does not take a block"
519
+ end
520
+
155
521
  at(-1)
156
522
  end
157
523
 
@@ -2,16 +2,27 @@
2
2
 
3
3
  module Remap
4
4
  class Constructor
5
- class Argument < Concrete
6
- using State::Extension
5
+ using State::Extension
7
6
 
7
+ # Allows a class (target) to be called with a regular argument
8
+ class Argument < Concrete
9
+ # @return [:argument]
8
10
  attribute :strategy, Value(:argument), default: :argument
9
11
 
10
- # Uses the {#method} method to initialize {#target} with {state}
11
- # Target is only called if {state} is defined
12
+ # Uses the {#method} method to initialize {#target} with state
13
+ # Target is only called if state is defined
14
+ #
15
+ # Used by {Remap::Base} to define constructors for mapped data
12
16
  #
13
17
  # Fails if {#target} does not respond to {#method}
14
- # Fails if {#target} cannot be called with {state}
18
+ # Fails if {#target} cannot be called with state
19
+ #
20
+ # @example Initialize a target with a state
21
+ # target = ::Struct.new(:foo)
22
+ # constructor = Remap::Constructor.call(strategy: :argument, target: target, method: :new)
23
+ # state = Remap::State.call(:bar)
24
+ # new_state = constructor.call(state)
25
+ # new_state.fetch(:value).foo # => :bar
15
26
  #
16
27
  # @param state [State]
17
28
  #
@@ -20,7 +31,10 @@ module Remap
20
31
  super.fmap do |input|
21
32
  target.public_send(id, input)
22
33
  rescue ArgumentError => e
23
- raise e.exception("Could not load target [#{target}] using the argument strategy with [#{input}] (#{input.class})")
34
+ raise e.exception("Failed to create [%p] with input [%s] (%s)" % [
35
+ target, input,
36
+ input.class
37
+ ])
24
38
  end
25
39
  end
26
40
  end
@@ -2,15 +2,26 @@
2
2
 
3
3
  module Remap
4
4
  class Constructor
5
- class Keyword < Concrete
6
- using State::Extension
5
+ using State::Extension
7
6
 
7
+ # Allows a class (target) to be called with keyword arguments
8
+ class Keyword < Concrete
9
+ # @return [:keyword]
8
10
  attribute :strategy, Value(:keyword)
9
11
 
10
12
  # Calls {#target} as with keyword arguments
11
13
  #
12
14
  # Fails if {#target} does not respond to {#method}
13
- # Fails if {#target} cannot be called with {state}
15
+ # Fails if {#target} cannot be called with state
16
+ #
17
+ # Used by {Remap::Base} to define constructors for mapped data
18
+ #
19
+ # @example Initialize a target with a state
20
+ # target = OpenStruct
21
+ # constructor = Remap::Constructor.call(strategy: :keyword, target: target, method: :new)
22
+ # state = Remap::State.call({ foo: :bar })
23
+ # new_state = constructor.call(state)
24
+ # new_state.fetch(:value).foo # => :bar
14
25
  #
15
26
  # @param state [State]
16
27
  #
@@ -23,7 +34,12 @@ module Remap
23
34
 
24
35
  target.public_send(id, **input)
25
36
  rescue ArgumentError => e
26
- raise e.exception("Could not load target [#{target}] using the keyword strategy using [#{input}] (#{input.class})")
37
+ raise e.exception("Failed to create [%p] with input [%s] (%s}) using method %s" % [
38
+ target,
39
+ input,
40
+ input.class,
41
+ id
42
+ ])
27
43
  end
28
44
  end
29
45
  end
@@ -2,15 +2,14 @@
2
2
 
3
3
  module Remap
4
4
  class Constructor
5
+ # Default type used by {Remap::Base}
5
6
  class None < Concrete
6
7
  attribute :target, Types::Nothing
7
8
  attribute :strategy, Types::Any
8
9
  attribute :method, Types::Any
9
10
 
10
- # Just returns the input state
11
- #
12
- # Fails if {#target} does not respond to {#method}
13
- # Fails if {#target} cannot be called with {state}
11
+ # Used by {Remap::Base} as a default constructor
12
+ # Using it does nothing but return its input state
14
13
  #
15
14
  # @param state [State]
16
15
  #
@@ -2,8 +2,11 @@
2
2
 
3
3
  module Remap
4
4
  class Constructor < Dry::Interface
5
+ # @return [Any]
6
+ attribute :target, Types::Any, not_eql: Nothing
7
+
8
+ # @return [Symbol]
5
9
  attribute :method, Symbol, default: :new
6
- attribute :target, Types::Any.constrained(not_eql: Nothing)
7
10
 
8
11
  # Ensures {#target} responds to {#method}
9
12
  # Returns an error state unless above is true
@@ -19,12 +22,16 @@ module Remap
19
22
  end
20
23
  end
21
24
 
22
- def id
23
- attributes.fetch(:method)
24
- end
25
-
25
+ # @return [Proc]
26
26
  def to_proc
27
27
  method(:call).to_proc
28
28
  end
29
+
30
+ private
31
+
32
+ # @return [Symbol]
33
+ def id
34
+ attributes.fetch(:method)
35
+ end
29
36
  end
30
37
  end