view_component_reducible 0.1.2 → 0.1.3
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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5505b895dc07055d3d09ad5e466316aadab92321fd2b8a71c3889cc1284059f2
|
|
4
|
+
data.tar.gz: 66757165853350bb660d16605c935ec5072eb01aedf4dfaf62419ab4d1af5439
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a5a98ecba5e6ac762086bce05b77409360708c91489d6bbd23bba626e9cc0f6ed1f06ee138b90bcb44c68c06e4b35f4474365ea4b5baae3600283e261e1b09aa
|
|
7
|
+
data.tar.gz: b56697564e122c374d7291cd1955678af2fb79ca307351b74f4c39043e7912bebab33d4f2ae17d26644a46a42a6f9781267be0db27601b5bbad14affe7fa9a3d
|
|
@@ -20,17 +20,59 @@ module ViewComponentReducible
|
|
|
20
20
|
type = params.fetch('vcr_msg_type')
|
|
21
21
|
payload_json = params['vcr_msg_payload']
|
|
22
22
|
payload = payload_json && payload_json != '' ? JSON.parse(payload_json) : {}
|
|
23
|
-
|
|
23
|
+
build(type:, payload:)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
# Build a Msg with a normalized payload object.
|
|
27
|
+
# @param type [String, Symbol]
|
|
28
|
+
# @param payload [Object, nil]
|
|
29
|
+
# @return [ViewComponentReducible::Msg]
|
|
30
|
+
def self.build(type:, payload: nil)
|
|
31
|
+
return new(type:, payload:) if payload.is_a?(Data)
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
normalized = normalize_type(type)
|
|
34
|
+
new(type:, payload: self::Payload.from_hash(normalized, payload))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @param type [String, Symbol]
|
|
38
|
+
# @return [Symbol]
|
|
39
|
+
def self.normalize_type(type)
|
|
29
40
|
type.to_s
|
|
30
41
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
|
31
42
|
.tr('-', '_')
|
|
32
43
|
.downcase
|
|
33
44
|
.to_sym
|
|
34
45
|
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def normalized_type
|
|
50
|
+
self.class.normalize_type(type)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class Msg
|
|
55
|
+
module Payload
|
|
56
|
+
Empty = Data.define
|
|
57
|
+
Value = Data.define(:value)
|
|
58
|
+
|
|
59
|
+
def self.from_hash(_type, payload)
|
|
60
|
+
payload_hash = payload.is_a?(Hash) ? payload.transform_keys(&:to_s) : nil
|
|
61
|
+
|
|
62
|
+
return Empty.new if payload.nil? || (payload.respond_to?(:empty?) && payload.empty?)
|
|
63
|
+
return Value.new(value: payload) unless payload_hash
|
|
64
|
+
|
|
65
|
+
build_generic(payload_hash)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.build_generic(payload_hash)
|
|
69
|
+
return Empty.new if payload_hash.empty?
|
|
70
|
+
|
|
71
|
+
keys = payload_hash.keys.map(&:to_sym)
|
|
72
|
+
klass = Data.define(*keys)
|
|
73
|
+
values = keys.to_h { |key| [key, payload_hash[key.to_s]] }
|
|
74
|
+
klass.new(**values)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
35
77
|
end
|
|
36
78
|
end
|
|
@@ -48,34 +48,53 @@ module ViewComponentReducible
|
|
|
48
48
|
schema = component_klass.vcr_state_schema
|
|
49
49
|
state = schema.build_data(env['data'])
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
reducer_result = component.reduce(state, msg)
|
|
52
|
+
reduced_state, reducer_effects = case reducer_result
|
|
53
|
+
in state_only unless reducer_result.is_a?(Array)
|
|
54
|
+
[state_only, []]
|
|
55
|
+
in [state_only]
|
|
56
|
+
[state_only, []]
|
|
57
|
+
in [state_only, *effects]
|
|
58
|
+
[state_only, effects]
|
|
59
|
+
end
|
|
60
|
+
env['data'] = normalize_state(reduced_state, schema)
|
|
61
|
+
effects = normalize_effects(reducer_effects) + normalize_effects(build_effects(component, schema, env['data'],
|
|
62
|
+
msg))
|
|
54
63
|
|
|
55
64
|
run_effects(component_klass, env, effects, controller)
|
|
56
65
|
end
|
|
57
66
|
|
|
58
67
|
def run_effects(component_klass, env, effects, controller)
|
|
59
|
-
|
|
68
|
+
effects_queue = normalize_effects(effects).dup
|
|
69
|
+
return env if effects_queue.empty?
|
|
60
70
|
|
|
61
|
-
effects_queue = effects.dup
|
|
62
71
|
steps = 0
|
|
63
72
|
|
|
64
73
|
while (eff = effects_queue.shift)
|
|
65
74
|
steps += 1
|
|
66
75
|
raise 'Too many effect steps' if steps > MAX_EFFECT_STEPS
|
|
67
76
|
|
|
68
|
-
follow_msg = eff
|
|
77
|
+
follow_msg = resolve_effect_msg(eff, controller, env)
|
|
69
78
|
next unless follow_msg
|
|
79
|
+
raise ArgumentError, 'Effect must return a Msg' unless follow_msg.is_a?(Msg)
|
|
70
80
|
|
|
71
81
|
component = component_klass.new(vcr_envelope: env)
|
|
72
82
|
schema = component_klass.vcr_state_schema
|
|
73
83
|
state = schema.build_data(env['data'])
|
|
74
84
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
reducer_result = component.reduce(state, follow_msg)
|
|
86
|
+
reduced_state, reducer_effects = case reducer_result
|
|
87
|
+
in state_only unless reducer_result.is_a?(Array)
|
|
88
|
+
[state_only, []]
|
|
89
|
+
in [state_only]
|
|
90
|
+
[state_only, []]
|
|
91
|
+
in [state_only, *effects]
|
|
92
|
+
[state_only, effects]
|
|
93
|
+
end
|
|
94
|
+
env['data'] = normalize_state(reduced_state, schema)
|
|
95
|
+
new_effects = normalize_effects(reducer_effects) + normalize_effects(build_effects(component, schema,
|
|
96
|
+
env['data'], follow_msg))
|
|
97
|
+
effects_queue.concat(new_effects)
|
|
79
98
|
end
|
|
80
99
|
|
|
81
100
|
env
|
|
@@ -110,6 +129,17 @@ module ViewComponentReducible
|
|
|
110
129
|
Array(component.effects(state, msg))
|
|
111
130
|
end
|
|
112
131
|
|
|
132
|
+
def normalize_effects(effects)
|
|
133
|
+
Array(effects).compact
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def resolve_effect_msg(effect, controller, env)
|
|
137
|
+
return effect if effect.is_a?(Msg)
|
|
138
|
+
return effect.call(controller: controller, envelope: env) if effect.respond_to?(:call)
|
|
139
|
+
|
|
140
|
+
raise ArgumentError, 'Effect must respond to #call or be a Msg'
|
|
141
|
+
end
|
|
142
|
+
|
|
113
143
|
def deep_dup(obj)
|
|
114
144
|
Marshal.load(Marshal.dump(obj))
|
|
115
145
|
end
|