smash_the_state 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -12
- data/lib/smash_the_state/operation.rb +9 -0
- data/lib/smash_the_state/operation/dry_run.rb +7 -0
- data/lib/smash_the_state/operation/sequence.rb +15 -1
- data/lib/smash_the_state/operation/state.rb +2 -2
- data/lib/smash_the_state/version.rb +1 -1
- data/spec/unit/operation_spec.rb +29 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c239b6b0b7a6c2d025a9640781bfe3feea37887be11971a36641c21efdc89c29
|
4
|
+
data.tar.gz: 20b3cb0250ba5d589d76c327a32dcecb327a5626b2c300d0ff8962f0075f8e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1fb815ecf8fa1d672a400d1dea88ccafc00ecc571ccdbbe78803f55a12d25e343684ed62a2556711be9650b65251b50b97bec8adf1dd6396da10c845f240530
|
7
|
+
data.tar.gz: 7370311616f9a628e29abcc6c47d0a6728bf28eb274ebc5206e931cc1655741faa8a8b8c9c47908b80afbea36281d05dc14b02bd7c245cc2bed8dfe96bb41786
|
data/README.md
CHANGED
@@ -96,24 +96,23 @@ class CreateAnalyticsOperation < SmashTheState::Operation
|
|
96
96
|
end
|
97
97
|
```
|
98
98
|
|
99
|
-
## Dynamic
|
99
|
+
## Dynamic Schemas (built at runtime)
|
100
100
|
|
101
|
-
Maybe your operation needs a more flexible schema than a static state class can provide. If you need your state class to be evaluated at runtime, you can
|
101
|
+
Maybe your operation needs a more flexible schema than a static state class can provide. Maybe you need to base your schema on some other data model that isn't available at the time the class is evaluated. If you need your state class to be evaluated at runtime, you can specify `dynamic_schema` with a block. The raw params hash will be passed in as the initial state. From there you can create whatever state class you desire at runtime. Be careful with this because this can quickly get out of hand. If you find yourself using dynamic schemas frequently, you may actually want distinct operations with static schemas.
|
102
102
|
|
103
103
|
```ruby
|
104
|
-
class
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
class BillingStuff < SmashTheState::Operation
|
105
|
+
dynamic_schema do |params|
|
106
|
+
# let's say we want to base our schema on an external service.
|
107
|
+
# we can call the service and build our schema off of the keys it returns
|
108
|
+
# let's say it's something like {name: "...", id: "...", is_paid: "..."}
|
109
|
+
BillingService.get_billing_things.keys do |key|
|
110
|
+
attribute key, :string
|
109
111
|
end
|
110
|
-
|
111
|
-
c.new(params)
|
112
112
|
end
|
113
113
|
|
114
|
-
step :do_more_things do |state
|
115
|
-
#
|
116
|
-
# ... and so on
|
114
|
+
step :do_more_things do |state|
|
115
|
+
# ... we receive a state with name, id, and is_paid attributes ...
|
117
116
|
end
|
118
117
|
end
|
119
118
|
```
|
@@ -35,6 +35,15 @@ module SmashTheState
|
|
35
35
|
@state_class = Operation::State.build(&block)
|
36
36
|
end
|
37
37
|
|
38
|
+
def dynamic_schema(&block)
|
39
|
+
sequence.add_step :_dynamic_schema do |params|
|
40
|
+
Operation::State.build(params, &block).new(params)
|
41
|
+
end
|
42
|
+
|
43
|
+
# make sure that the dynamic schema step that we just added above is always first
|
44
|
+
sequence.steps.unshift sequence.steps.pop
|
45
|
+
end
|
46
|
+
|
38
47
|
def step(step_name, options = {}, &block)
|
39
48
|
sequence.add_step(step_name, options, &block)
|
40
49
|
end
|
@@ -7,6 +7,13 @@ module SmashTheState
|
|
7
7
|
def initialize(wet_sequence)
|
8
8
|
@wet_sequence = wet_sequence
|
9
9
|
@dry_sequence = Operation::Sequence.new
|
10
|
+
|
11
|
+
# in the case of a dynamic schema, front-load it as the first step
|
12
|
+
dynamic_schema_step = @wet_sequence.dynamic_schema_step
|
13
|
+
|
14
|
+
return if dynamic_schema_step.nil?
|
15
|
+
|
16
|
+
step(dynamic_schema_step.name, &dynamic_schema_step.implementation)
|
10
17
|
end
|
11
18
|
|
12
19
|
def step(step_name, &block)
|
@@ -115,12 +115,26 @@ module SmashTheState
|
|
115
115
|
@steps << step
|
116
116
|
end
|
117
117
|
|
118
|
+
def dynamic_schema?
|
119
|
+
dynamic_schema_step.nil? == false
|
120
|
+
end
|
121
|
+
|
122
|
+
def dynamic_schema_step
|
123
|
+
steps_for_name(:_dynamic_schema).first
|
124
|
+
end
|
125
|
+
|
118
126
|
private
|
119
127
|
|
128
|
+
def make_original_state(state)
|
129
|
+
return dynamic_schema_step.implementation.call(state, state, run_options) if dynamic_schema?
|
130
|
+
|
131
|
+
state.dup
|
132
|
+
end
|
133
|
+
|
120
134
|
def run_steps(steps_to_run, state)
|
121
135
|
# retain a copy of the original state so that we can refer to it for posterity as
|
122
136
|
# the operation state gets mutated over time
|
123
|
-
original_state = state
|
137
|
+
original_state = make_original_state(state)
|
124
138
|
current_step = nil
|
125
139
|
|
126
140
|
steps_to_run.reduce(state) do |memo, s|
|
data/spec/unit/operation_spec.rb
CHANGED
@@ -191,6 +191,35 @@ describe SmashTheState::Operation do
|
|
191
191
|
end
|
192
192
|
end
|
193
193
|
|
194
|
+
describe "self#dynamic_schema" do
|
195
|
+
let!(:klass) do
|
196
|
+
Class.new(SmashTheState::Operation).tap do |k|
|
197
|
+
k.class_eval do
|
198
|
+
dynamic_schema do |params|
|
199
|
+
attribute "#{params[:adjective]}_#{params[:animal]}", :string
|
200
|
+
end
|
201
|
+
|
202
|
+
step :step_one do |state|
|
203
|
+
state.fat_ocelot = "maybe"
|
204
|
+
state
|
205
|
+
end
|
206
|
+
|
207
|
+
step :step_two do |state, original_state|
|
208
|
+
[state, original_state]
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
it "produces an 'inline' schema that is evaluated each time the operation "\
|
215
|
+
"runs while passing the 'original' dynamic state onto the next step" do
|
216
|
+
state, original_state = klass.call(adjective: "fat", animal: "ocelot", fat_ocelot: "no")
|
217
|
+
|
218
|
+
expect(state.fat_ocelot).to eq("maybe")
|
219
|
+
expect(original_state.fat_ocelot).to eq("no")
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
194
223
|
describe "self#dry_run_sequence" do
|
195
224
|
context "with a custom dry run sequence block" do
|
196
225
|
before do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smash_the_state
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dan Connor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-08-
|
11
|
+
date: 2019-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_model_attributes
|