remap 2.0.2 → 2.1.5

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