remap 2.1.13 → 2.1.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 526ddded05ad56900a9f6d1276069c48297adc6f5cb32ef08b955949bf9ee426
4
- data.tar.gz: 239295549c9f0365453d19254fe21ff046755b6066f86a81596abaf102a98bbb
3
+ metadata.gz: 88204af4f42ce85893ec029d953e2e6c417bbacba673522eedadca9561f8f749
4
+ data.tar.gz: 9e3e6040baf0426590b4c920d33f0979e74a084a19bbd87079d474a9e251663a
5
5
  SHA512:
6
- metadata.gz: 1c8d02457838ffe470359e5b9ff97cd2a31288928d238362eb38d85c190160b430242d2cfb401e9f7dbb418be4838dd6cbb1c282b68a7eababf5ad2d48030440
7
- data.tar.gz: 191f1570f40e582c31e724e788882b54f83ff82e6d37931519451975355ceab5fb708260352523ddc10c849daa86d31c915221e9d539f2c069288462ca5dc45b
6
+ metadata.gz: 612cf547b8207f305cf9b1f4788d3b36c0d487f0c42bdbf657336c04982060f6dd46a0cfc2a57c39588cef15287ede98205ab5beb46c9245b3270a99b586934d
7
+ data.tar.gz: a11492555b465f2d9f2db0611ed8d6457579dc6546805a9a867fc7b951061572f0faae84caec4be50907efa99e15647a8ae52aefd0de14362d29d6fea45cb166
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Remap
4
+ using State::Extension
5
+
4
6
  # Constructs a {Rule} from the block passed to {Remap::Base.define}
5
7
  class Compiler < Proxy
6
8
  # @return [Array<Rule>]
@@ -29,12 +31,18 @@ module Remap
29
31
  # @return [Rule]
30
32
  def self.call(&block)
31
33
  unless block
32
- return Rule::Void.new
34
+ return Rule::VOID
33
35
  end
34
36
 
35
- new([]).tap do |compiler|
37
+ rules = new([]).tap do |compiler|
36
38
  compiler.instance_exec(&block)
37
- end.rule
39
+ end.rules
40
+
41
+ if rules.empty?
42
+ return Rule::VOID
43
+ end
44
+
45
+ Rule::Block.new(rules)
38
46
  end
39
47
 
40
48
  # Maps input path [input] to output path [to]
@@ -59,13 +67,7 @@ module Remap
59
67
  #
60
68
  # @return [Rule::Map::Required]
61
69
  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))
70
+ add rule(*path, to: to, backtrace: backtrace, &block)
69
71
  end
70
72
 
71
73
  # Optional version of {#map}
@@ -92,13 +94,7 @@ module Remap
92
94
  #
93
95
  # @return [Rule::Map::Optional]
94
96
  def map?(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
95
- add Rule::Map::Optional.call(
96
- path: {
97
- output: [to].flatten,
98
- input: path.flatten
99
- },
100
- backtrace: backtrace,
101
- rule: call(&block))
97
+ add rule?(*path, to: to, backtrace: backtrace, &block)
102
98
  end
103
99
 
104
100
  # Select a path and uses the same path as output
@@ -122,7 +118,7 @@ module Remap
122
118
  #
123
119
  # @return [Rule::Map::Required]
124
120
  def get(*path, backtrace: Kernel.caller, &block)
125
- map(path, to: path, backtrace: backtrace, &block)
121
+ add rule(path, to: path, backtrace: backtrace, &block)
126
122
  end
127
123
 
128
124
  # Optional version of {#get}
@@ -147,7 +143,7 @@ module Remap
147
143
  #
148
144
  # @return [Rule::Map::Optional]
149
145
  def get?(*path, backtrace: Kernel.caller, &block)
150
- map?(path, to: path, backtrace: backtrace, &block)
146
+ add rule?(path, to: path, backtrace: backtrace, &block)
151
147
  end
152
148
 
153
149
  # Maps using mapper
@@ -189,9 +185,13 @@ module Remap
189
185
  raise ArgumentError, "#embed does not take a block"
190
186
  end
191
187
 
192
- add Rule::Embed.new(mapper: mapper)
193
- rescue Dry::Struct::Error
194
- raise ArgumentError, "Embeded mapper must be [Remap::Mapper], got [#{mapper}]"
188
+ embeding = rule(&block).add do |state, &error|
189
+ mapper.call!(state.set(mapper: mapper)) do |failure|
190
+ next error[failure]
191
+ end.except(:mapper, :scope)
192
+ end
193
+
194
+ add embeding
195
195
  end
196
196
 
197
197
  # Set a static value
@@ -234,9 +234,7 @@ module Remap
234
234
  raise ArgumentError, "#set does not take a block"
235
235
  end
236
236
 
237
- add Rule::Set.new(path: path.flatten, value: to)
238
- rescue Dry::Struct::Error => e
239
- raise ArgumentError, e.message
237
+ add rule(to: path).add { to.call(_1) }
240
238
  end
241
239
 
242
240
  # Maps to path from map with block in between
@@ -261,7 +259,7 @@ module Remap
261
259
  #
262
260
  # @return [Rule::Map]
263
261
  def to(*path, map: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
264
- map(*map, to: path, backtrace: backtrace, &block)
262
+ add rule(*map, to: path, backtrace: backtrace, &block)
265
263
  end
266
264
 
267
265
  # Optional version of {#to}
@@ -287,7 +285,7 @@ module Remap
287
285
  #
288
286
  # @return [Rule::Map::Optional]
289
287
  def to?(*path, map: EMPTY_ARRAY, &block)
290
- map?(*map, to: path, &block)
288
+ add rule?(*map, to: path, &block)
291
289
  end
292
290
 
293
291
  # Iterates over the input value, passes each value
@@ -319,7 +317,7 @@ module Remap
319
317
  raise ArgumentError, "#each requires a block"
320
318
  end
321
319
 
322
- add Rule::Each.new(rule: call(&block))
320
+ add rule(all, &block)
323
321
  end
324
322
 
325
323
  # Wraps output in type
@@ -352,9 +350,7 @@ module Remap
352
350
  raise ArgumentError, "#wrap requires a block"
353
351
  end
354
352
 
355
- add Rule::Wrap.new(type: type, rule: call(&block))
356
- rescue Dry::Struct::Error => e
357
- raise ArgumentError, e.message
353
+ add rule(&block).then { Array.wrap(_1) }
358
354
  end
359
355
 
360
356
  # Selects all elements
@@ -521,19 +517,31 @@ module Remap
521
517
  at(-1)
522
518
  end
523
519
 
524
- # The final rule
525
- #
526
- # @return [Rule]
527
- #
528
- # @private
529
- def rule
530
- Rule::Collection.call(rules: rules)
531
- end
532
-
533
520
  private
534
521
 
535
522
  def add(rule)
536
523
  rule.tap { rules << rule }
537
524
  end
525
+
526
+ def rule(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
527
+ Rule::Map::Required.call({
528
+ path: {
529
+ output: [to].flatten,
530
+ input: path.flatten
531
+ },
532
+ backtrace: backtrace,
533
+ rule: call(&block)
534
+ })
535
+ end
536
+
537
+ def rule?(*path, to: EMPTY_ARRAY, backtrace: Kernel.caller, &block)
538
+ Rule::Map::Optional.call({
539
+ path: {
540
+ output: [to].flatten,
541
+ input: path.flatten
542
+ },
543
+ rule: call(&block)
544
+ })
545
+ end
538
546
  end
539
547
  end
@@ -38,6 +38,8 @@ module Remap
38
38
  end
39
39
 
40
40
  [current_path + [key], value]
41
+ rescue TypeError
42
+ raise PathError, current_path + [key]
41
43
  end
42
44
 
43
45
  result
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remap
4
+ class Rule
5
+ using State::Extension
6
+
7
+ class Block < Unit
8
+ # @return [Array<Rule>]
9
+ attribute :rules, [Types::Rule]
10
+
11
+ # Represents a non-empty define block with one or more rules
12
+ # Calls every {#rules} with state and merges the output
13
+ #
14
+ # @param state [State]
15
+ #
16
+ # @return [State]
17
+ def call(state, &error)
18
+ unless block_given?
19
+ raise ArgumentError, "Block#call(state, &error) requires a block"
20
+ end
21
+
22
+ if rules.empty?
23
+ return state.except(:value)
24
+ end
25
+
26
+ rules.map do |rule|
27
+ rule.call(state) do |failure|
28
+ return error[failure]
29
+ end
30
+ end.reduce(&:combine)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Remap
4
+ class Rule
5
+ class Map
6
+ class Enum < Proxy
7
+ include Dry::Monads[:maybe]
8
+
9
+ # @return [Hash]
10
+ option :mappings, default: -> { Hash.new { default } }
11
+
12
+ # @return [Maybe]
13
+ option :default, default: -> { None() }
14
+
15
+ alias execute instance_eval
16
+
17
+ # Builds an enumeration using the block as context
18
+ #
19
+ # @example
20
+ # enum = Remap::Rule::Map::Enum.call do
21
+ # from "B", to: "C"
22
+ # value "A"
23
+ # otherwise "D"
24
+ # end
25
+ #
26
+ # enum.get("A") # => "A"
27
+ # enum.get("B") # => "C"
28
+ # enum.get("C") # => "C"
29
+ # enum.get("MISSING") # => "D"
30
+ #
31
+ # @return [Any]
32
+ def self.call(&block)
33
+ unless block
34
+ raise ArgumentError, "no block given"
35
+ end
36
+
37
+ new.tap { _1.execute(&block) }
38
+ end
39
+
40
+ # Translates key into a value using predefined mappings
41
+ #
42
+ # @param key [#hash]
43
+ #
44
+ # @yield [String]
45
+ # If the key is not found & no default value is set
46
+ #
47
+ # @return [Any]
48
+ def get(key, &error)
49
+ unless error
50
+ return get(key) { raise Error, _1 }
51
+ end
52
+
53
+ self[key].bind { return _1 }.or do
54
+ error["Enum key [#{key}] not found among [#{mappings.keys.inspect}]"]
55
+ end
56
+ end
57
+ alias call get
58
+
59
+ # @return [Maybe]
60
+ def [](key)
61
+ mappings[key]
62
+ end
63
+
64
+ # @return [void]
65
+ def from(*keys, to:)
66
+ value = Some(to)
67
+
68
+ keys.each do |key|
69
+ mappings[key] = value
70
+ mappings[to] = value
71
+ end
72
+ end
73
+
74
+ # @return [void]
75
+ def value(*ids)
76
+ ids.each do |id|
77
+ from(id, to: id)
78
+ end
79
+ end
80
+
81
+ # @return [void]
82
+ def otherwise(value)
83
+ mappings.default = Some(value)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -31,7 +31,7 @@ module Remap
31
31
  #
32
32
  # @return [State]
33
33
  def call(state, &error)
34
- unless error
34
+ unless block_given?
35
35
  raise ArgumentError, "map.call(state, &error) requires a block"
36
36
  end
37
37
 
@@ -43,15 +43,19 @@ module Remap
43
43
  #
44
44
  # @abstract
45
45
  def call(state, &error)
46
- unless error
46
+ unless block_given?
47
47
  raise ArgumentError, "Map#call(state, &error) requires error handler block"
48
48
  end
49
49
 
50
50
  notice = catch :fatal do
51
51
  return path.input.call(state) do |inner_state|
52
- rule.call(inner_state) do |failure|
52
+ other_state = rule.call(inner_state) do |failure|
53
53
  return error[failure]
54
- end.then(&callback)
54
+ end
55
+
56
+ callback(other_state) do |failure|
57
+ return error[failure]
58
+ end
55
59
  end.then(&path.output)
56
60
  end
57
61
 
@@ -181,23 +185,27 @@ module Remap
181
185
  end
182
186
  end
183
187
 
184
- private
185
-
186
188
  # @return [self]
187
189
  def add(&block)
188
190
  tap { fn << block }
189
191
  end
190
192
 
193
+ private
194
+
191
195
  # @return [Array<Proc>]
192
196
  def fn
193
197
  @fn ||= []
194
198
  end
195
199
 
196
200
  # @return [Proc]
197
- def callback
198
- -> state do
199
- fn.reduce(state) do |inner, fn|
200
- fn[inner]
201
+ def callback(state, &error)
202
+ unless block_given?
203
+ raise ArgumentError, "Map#callback(state, &error) requires error handler block"
204
+ end
205
+
206
+ fn.reduce(state) do |inner, fn|
207
+ fn[inner] do |failure|
208
+ return error[failure]
201
209
  end
202
210
  end
203
211
  end
data/lib/remap/rule.rb CHANGED
@@ -5,6 +5,8 @@ module Remap
5
5
  defines :requirement
6
6
  requirement Types::Any
7
7
 
8
+ VOID = Void.new(EMPTY_HASH)
9
+
8
10
  # @param state [State]
9
11
  #
10
12
  # @abstract
@@ -8,8 +8,15 @@ module Remap
8
8
  #
9
9
  # @example Select the value at index 1 from a array
10
10
  # state = Remap::State.call([:one, :two, :tree])
11
- # result = Remap::Selector::Index.new(1).call(state)
12
- # result.fetch(:value) # => :two
11
+ # index = Remap::Selector::Index.new(1)
12
+ #
13
+ # result = index.call(state) do |element|
14
+ # element.fmap do |value|
15
+ # value.upcase
16
+ # end
17
+ # end
18
+
19
+ # result.fetch(:value) # => :TWO
13
20
  class Index < Unit
14
21
  # @return [Integer]
15
22
  attribute :index, Integer
@@ -25,7 +32,9 @@ module Remap
25
32
  #
26
33
  # @return [State<U>]
27
34
  def call(outer_state, &block)
28
- return call(outer_state, &:itself) unless block
35
+ unless block_given?
36
+ raise ArgumentError, "The index selector requires an iteration block"
37
+ end
29
38
 
30
39
  outer_state.bind(index: index) do |array, state|
31
40
  requirement[array] do
@@ -351,7 +351,7 @@ module Remap
351
351
  #
352
352
  # @return [Struct]
353
353
  def context(value, context: self, &error)
354
- ::Struct.new(*keys, *options.keys, keyword_init: true) do
354
+ ::Struct.new(*keys, *options.keys, :state, keyword_init: true) do
355
355
  define_method :method_missing do |name, *|
356
356
  error["Method [#{name}] not defined"]
357
357
  end
@@ -359,7 +359,7 @@ module Remap
359
359
  define_method :skip! do |message = "Manual skip!"|
360
360
  context.ignore!(message)
361
361
  end
362
- end.new(**to_hash, **options, value: value)
362
+ end.new(**to_hash, **options, value: value, state: self)
363
363
  end
364
364
  end
365
365
  end
data/lib/remap/types.rb CHANGED
@@ -15,7 +15,7 @@ module Remap
15
15
  Enumerable = Any.constrained(type: Enumerable)
16
16
  Nothing = Constant(Remap::Nothing)
17
17
  Mapper = Interface(:call!)
18
- Rule = Interface(:call)
18
+ Rule = Interface(:call) | Instance(Proc)
19
19
  Key = Interface(:hash)
20
20
 
21
21
  # Validates a state according to State::Schema
data/lib/remap.rb CHANGED
@@ -17,7 +17,6 @@ require "zeitwerk"
17
17
 
18
18
  module Remap
19
19
  loader = Zeitwerk::Loader.for_gem
20
- loader.collapse("#{__dir__}/remap/rule/support")
21
20
  loader.collapse("#{__dir__}/remap/mapper/support")
22
21
  loader.setup
23
22
  loader.eager_load
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: remap
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.13
4
+ version: 2.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Linus Oleander
@@ -279,18 +279,12 @@ files:
279
279
  - lib/remap/path_error.rb
280
280
  - lib/remap/proxy.rb
281
281
  - lib/remap/rule.rb
282
- - lib/remap/rule/each.rb
283
- - lib/remap/rule/embed.rb
282
+ - lib/remap/rule/block.rb
284
283
  - lib/remap/rule/map.rb
284
+ - lib/remap/rule/map/enum.rb
285
285
  - lib/remap/rule/map/optional.rb
286
286
  - lib/remap/rule/map/required.rb
287
- - lib/remap/rule/set.rb
288
- - lib/remap/rule/support/collection.rb
289
- - lib/remap/rule/support/collection/empty.rb
290
- - lib/remap/rule/support/collection/filled.rb
291
- - lib/remap/rule/support/enum.rb
292
287
  - lib/remap/rule/void.rb
293
- - lib/remap/rule/wrap.rb
294
288
  - lib/remap/selector.rb
295
289
  - lib/remap/selector/all.rb
296
290
  - lib/remap/selector/index.rb
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- using State::Extension
6
-
7
- # Iterates over a rule, even if the rule is not a collection
8
- #
9
- # @example Upcase each value in an array
10
- # state = Remap::State.call(["John", "Jane"])
11
- # upcase = Remap::Rule::Map.call({}).then(&:upcase)
12
- # each = Remap::Rule::Each.call(rule: upcase)
13
- # error = -> failure { raise failure.exception }
14
- # each.call(state, &error).fetch(:value) # => ["JOHN", "JANE"]
15
- class Each < Unit
16
- # @return [Rule]
17
- attribute :rule, Types::Rule
18
-
19
- # Iterates over state and passes each value to rule
20
- # Restores element, key & index before returning state
21
- #
22
- # @param state [State<Enumerable>]
23
- #
24
- # @return [State<Enumerable>]
25
- def call(state, &error)
26
- unless error
27
- raise ArgumentError, "Each#call(state, &error) requires a block"
28
- end
29
-
30
- state.map do |inner_state|
31
- rule.call(inner_state) do |failure|
32
- return error[failure]
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- using State::Extension
6
-
7
- # Embed mappers into each other
8
- #
9
- # @example Embed Mapper A into B
10
- # class Car < Remap::Base
11
- # define do
12
- # map :name, to: :model
13
- # end
14
- # end
15
- #
16
- # class Person < Remap::Base
17
- # define do
18
- # to :person do
19
- # to :car do
20
- # embed Car
21
- # end
22
- # end
23
- # end
24
- # end
25
- #
26
- # Person.call({name: "Volvo"}) # => { person: { car: { model: "Volvo" } } }
27
- class Embed < Unit
28
- # @return [#call!]
29
- attribute :mapper, Types::Mapper
30
-
31
- # Evaluates input against mapper and returns the result
32
- #
33
- # @param state [State<T>]
34
- #
35
- # @return [State<U>]
36
- def call(state, &error)
37
- unless error
38
- raise ArgumentError, "A block is required to evaluate the embed"
39
- end
40
-
41
- mapper.call!(state.set(mapper: mapper)) do |failure|
42
- return error[failure]
43
- end.except(:mapper, :scope)
44
- end
45
- end
46
- end
47
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- using State::Extension
6
-
7
- # Set path to a static value
8
- #
9
- # @example Set path [:a, :b] to value "C"
10
- # value = Remap::Static::Fixed.new(value: "a value")
11
- # set = Remap::Rule::Set.new(value: value, path: [:a, :b])
12
- # state = Remap::State.call("ANY VALUE")
13
- # set.call(state).fetch(:value) # => { a: { b: "a value" } }
14
- #
15
- # @example Set path [:a, :b] to option :c
16
- # value = Remap::Static::Option.new(name: :c)
17
- # set = Remap::Rule::Set.new(value: value, path: [:a, :b])
18
- # state = Remap::State.call("ANY VALUE", options: { c: "C" })
19
- # set.call(state).fetch(:value) # => { a: { b: "C" } }
20
- class Set < Concrete
21
- # @return [Static]
22
- attribute :value, Static, alias: :rule
23
-
24
- # @return [Path::Output]
25
- attribute :path, Path::Output
26
-
27
- # @see Rule#call
28
- def call(...)
29
- rule.call(...).then(&path)
30
- end
31
- end
32
- end
33
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- class Collection
6
- using State::Extension
7
-
8
- # Represents an empty rule block
9
- class Empty < Unit
10
- attribute? :rules, Value(EMPTY_ARRAY), default: EMPTY_ARRAY
11
-
12
- # Represents an empty define block, without any rules
13
- #
14
- # @param state [State<T>]
15
- #
16
- # @return [State<T>]
17
- def call(state)
18
- state.notice!("No rules, empty block")
19
- end
20
- end
21
- end
22
- end
23
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- class Collection
6
- using State::Extension
7
-
8
- # Represents a non-empty rule block
9
- #
10
- # @example A collection containing a single rule
11
- # state = Remap::State.call("A")
12
- # void = Remap::Rule::Void.call({})
13
- # rule = Remap::Rule::Collection.call([void])
14
- # error = -> failure { raise failure.exception }
15
- # rule.call(state, &error).fetch(:value) # => "A"
16
- class Filled < Unit
17
- # @return [Array<Rule>]
18
- attribute :rules, [Types.Interface(:call)], min_size: 1
19
-
20
- # Represents a non-empty define block with one or more rules
21
- # Calls every {#rules} with state and merges the output
22
- #
23
- # @param state [State]
24
- #
25
- # @return [State]
26
- def call(state, &error)
27
- unless error
28
- raise ArgumentError, "Collection::Filled#call(state, &error) requires a block"
29
- end
30
-
31
- rules.map do |rule|
32
- rule.call(state) do |failure|
33
- return error[failure]
34
- end
35
- end.reduce(&:combine)
36
- end
37
- end
38
- end
39
- end
40
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- # Represents a block defined by a rule
6
- class Collection < Abstract
7
- attribute :rules, Array
8
-
9
- # @param state [State]
10
- #
11
- # @return [State]
12
- #
13
- # @abstract
14
- def call(state)
15
- raise NotImplementedError, "#{self.class}#call not implemented"
16
- end
17
- end
18
- end
19
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- class Enum < Proxy
6
- include Dry::Monads[:maybe]
7
-
8
- # @return [Hash]
9
- option :mappings, default: -> { Hash.new { default } }
10
-
11
- # @return [Maybe]
12
- option :default, default: -> { None() }
13
-
14
- alias execute instance_eval
15
-
16
- # Builds an enumeration using the block as context
17
- #
18
- # @example
19
- # enum = Remap::Rule::Enum.call do
20
- # from "B", to: "C"
21
- # value "A"
22
- # otherwise "D"
23
- # end
24
- #
25
- # enum.get("A") # => "A"
26
- # enum.get("B") # => "C"
27
- # enum.get("C") # => "C"
28
- # enum.get("MISSING") # => "D"
29
- #
30
- # @return [Any]
31
- def self.call(&block)
32
- unless block
33
- raise ArgumentError, "no block given"
34
- end
35
-
36
- new.tap { _1.execute(&block) }
37
- end
38
-
39
- # Translates key into a value using predefined mappings
40
- #
41
- # @param key [#hash]
42
- #
43
- # @yield [String]
44
- # If the key is not found & no default value is set
45
- #
46
- # @return [Any]
47
- def get(key, &error)
48
- unless error
49
- return get(key) { raise Error, _1 }
50
- end
51
-
52
- self[key].bind { return _1 }.or do
53
- error["Enum key [#{key}] not found among [#{mappings.keys.inspect}]"]
54
- end
55
- end
56
- alias call get
57
-
58
- # @return [Maybe]
59
- def [](key)
60
- mappings[key]
61
- end
62
-
63
- # @return [void]
64
- def from(*keys, to:)
65
- value = Some(to)
66
-
67
- keys.each do |key|
68
- mappings[key] = value
69
- mappings[to] = value
70
- end
71
- end
72
-
73
- # @return [void]
74
- def value(*ids)
75
- ids.each do |id|
76
- from(id, to: id)
77
- end
78
- end
79
-
80
- # @return [void]
81
- def otherwise(value)
82
- mappings.default = Some(value)
83
- end
84
- end
85
- end
86
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Remap
4
- class Rule
5
- using State::Extension
6
-
7
- # Wraps rule in a type
8
- #
9
- # @example Maps { name: "Ford" } to { cars: ["Ford"] }
10
- # class Mapper < Remap::Base
11
- # define do
12
- # to :cars do
13
- # wrap(:array) do
14
- # map :name
15
- # end
16
- # end
17
- # end
18
- # end
19
- #
20
- # Mapper.call({ name: "Ford" }) # => { cars: ["Ford"] }
21
- class Wrap < Concrete
22
- # @return [:array]
23
- attribute :type, Value(:array)
24
-
25
- # @return [Rule]
26
- attribute :rule, Types::Rule
27
-
28
- # Wraps the output from {#rule} in a {#type}
29
- #
30
- # @see Rule#call
31
- def call(...)
32
- rule.call(...).fmap do |value|
33
- Array.wrap(value)
34
- end
35
- end
36
- end
37
- end
38
- end