statefully 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 +4 -4
- data/lib/statefully/diff.rb +61 -36
- data/lib/statefully/inspect.rb +14 -0
- data/lib/statefully/state.rb +9 -14
- data/lib/statefully.rb +1 -0
- data/spec/diff_spec.rb +34 -0
- data/spec/state_spec.rb +23 -9
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97acdf9e907dd51ad5227ef53828030d0943d35d
|
4
|
+
data.tar.gz: 3d9564c5fa59479e584e38c94ebdf504e1e1894d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 94467d76d84d115d674c84db44022a6c4e76d81e417b1ca48eb613734802fd80c420f4a79832aa248f1622e9260c26d1bdfb8c72f9c73f078a14df230cde96b5
|
7
|
+
data.tar.gz: 732e6d9e831787099ae318d706a0c6d95280ea8ee06217e1bc0b3f9a30bd058d150b8053a972ffd631a626e3e75937cac403a5fc9e14609f0413f870e6da9894
|
data/lib/statefully/diff.rb
CHANGED
@@ -2,52 +2,55 @@ require 'set'
|
|
2
2
|
require 'singleton'
|
3
3
|
|
4
4
|
module Statefully
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
module Diff
|
6
|
+
# This method reeks of :reek:FeatureEnvy (of current).
|
7
|
+
def create(current, previous)
|
8
|
+
return current.diff if current.failed? || current.finished?
|
9
9
|
changes = Builder.new(current, previous).build
|
10
|
-
changes.empty? ?
|
10
|
+
changes.empty? ? Unchanged.instance : Changed.new(**changes).freeze
|
11
11
|
end
|
12
|
+
module_function :create
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
14
|
+
class Changed
|
15
|
+
attr_reader :added, :changed
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
def empty?
|
18
|
+
false
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class.name} #{inspect_details}>"
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def added?(key)
|
26
|
+
added.key?(key)
|
27
|
+
end
|
28
28
|
|
29
|
-
|
29
|
+
def changed?(key)
|
30
|
+
changed.key?(key)
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
[inspect_added, inspect_changed].compact.join(', ')
|
33
|
-
end
|
33
|
+
private
|
34
34
|
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def inspect_details
|
36
|
+
[inspect_added, inspect_changed].compact.join(', ')
|
37
|
+
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
def inspect_added
|
40
|
+
added.empty? ? nil : "added=#{Inspect.from_hash(added)}"
|
41
|
+
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
43
|
+
def inspect_changed
|
44
|
+
changed.empty? ? nil : "changed=#{Inspect.from_hash(changed)}"
|
45
|
+
end
|
47
46
|
|
48
|
-
|
49
|
-
|
47
|
+
def initialize(added:, changed:)
|
48
|
+
@added = added.freeze
|
49
|
+
@changed = changed.freeze
|
50
|
+
end
|
51
|
+
end # class Changed
|
50
52
|
|
53
|
+
module NoChanges
|
51
54
|
def empty?
|
52
55
|
true
|
53
56
|
end
|
@@ -59,11 +62,33 @@ module Statefully
|
|
59
62
|
def changed
|
60
63
|
{}
|
61
64
|
end
|
65
|
+
end # module NoChanges
|
66
|
+
private_constant :NoChanges
|
67
|
+
|
68
|
+
class Unchanged
|
69
|
+
include Singleton
|
70
|
+
include NoChanges
|
62
71
|
|
63
72
|
def inspect
|
64
|
-
"
|
73
|
+
"#<#{self.class.name}>"
|
65
74
|
end
|
66
|
-
end # class
|
75
|
+
end # class Unchanged
|
76
|
+
|
77
|
+
class Failed
|
78
|
+
include NoChanges
|
79
|
+
attr_reader :error
|
80
|
+
|
81
|
+
def initialize(error)
|
82
|
+
@error = error
|
83
|
+
end
|
84
|
+
|
85
|
+
def inspect
|
86
|
+
"#<#{self.class.name} error=#{error.inspect}>"
|
87
|
+
end
|
88
|
+
end # class Failed
|
89
|
+
|
90
|
+
class Finished < Unchanged
|
91
|
+
end # class Finished
|
67
92
|
|
68
93
|
class Change
|
69
94
|
attr_reader :current, :previous
|
@@ -127,5 +152,5 @@ module Statefully
|
|
127
152
|
end
|
128
153
|
end # class Builder
|
129
154
|
private_constant :Builder
|
130
|
-
end #
|
155
|
+
end # module Diff
|
131
156
|
end # module Statefully
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Statefully
|
2
|
+
module Inspect
|
3
|
+
def from_hash(input)
|
4
|
+
'{' + input.map { |key, val| "#{key}: #{val.inspect}" }.join(', ') + '}'
|
5
|
+
end
|
6
|
+
module_function :from_hash
|
7
|
+
|
8
|
+
def from_fields(input)
|
9
|
+
input.map { |key, val| "#{key}=#{val.inspect}" }.join(', ')
|
10
|
+
end
|
11
|
+
module_function :from_fields
|
12
|
+
end # module Inspect
|
13
|
+
private_constant :Inspect
|
14
|
+
end # module Statefully
|
data/lib/statefully/state.rb
CHANGED
@@ -21,12 +21,12 @@ module Statefully
|
|
21
21
|
([diff] + previous.history).freeze
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def successful?
|
25
25
|
true
|
26
26
|
end
|
27
27
|
|
28
|
-
def
|
29
|
-
!
|
28
|
+
def failed?
|
29
|
+
!successful?
|
30
30
|
end
|
31
31
|
|
32
32
|
def finished?
|
@@ -129,10 +129,10 @@ module Statefully
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def diff
|
132
|
-
error
|
132
|
+
Diff::Failed.new(error).freeze
|
133
133
|
end
|
134
134
|
|
135
|
-
def
|
135
|
+
def successful?
|
136
136
|
false
|
137
137
|
end
|
138
138
|
|
@@ -146,9 +146,12 @@ module Statefully
|
|
146
146
|
end # class Failure
|
147
147
|
private_constant :Failure
|
148
148
|
|
149
|
+
# Finished state is a state which is successful, but should not be processed
|
150
|
+
# any further. This could be useful for things like early returns.
|
149
151
|
class Finished < State
|
152
|
+
# This method reeks of :reek:UtilityFunction - just implementing an API.
|
150
153
|
def diff
|
151
|
-
|
154
|
+
Diff::Finished.instance
|
152
155
|
end
|
153
156
|
|
154
157
|
def finished?
|
@@ -156,13 +159,5 @@ module Statefully
|
|
156
159
|
end
|
157
160
|
end # class Finished
|
158
161
|
private_constant :Finished
|
159
|
-
|
160
|
-
module Inspect
|
161
|
-
def from_fields(input)
|
162
|
-
input.map { |key, val| "#{key}=#{val.inspect}" }.join(', ')
|
163
|
-
end
|
164
|
-
module_function :from_fields
|
165
|
-
end # module Inspect
|
166
|
-
private_constant :Inspect
|
167
162
|
end # class State
|
168
163
|
end # module Statefully
|
data/lib/statefully.rb
CHANGED
data/spec/diff_spec.rb
CHANGED
@@ -13,6 +13,9 @@ module Statefully
|
|
13
13
|
it { expect(subject.added?(:key)).to be_truthy }
|
14
14
|
it { expect(subject.added.fetch(:key)).to eq 'val' }
|
15
15
|
it { expect(subject.changed).to be_empty }
|
16
|
+
|
17
|
+
it { expect(subject.inspect).to start_with '#<Statefully::Diff::Changed' }
|
18
|
+
it { expect(subject.inspect).to include 'added={key: "val"}>' }
|
16
19
|
end # context 'when key added'
|
17
20
|
|
18
21
|
context 'when key changed' do
|
@@ -24,6 +27,8 @@ module Statefully
|
|
24
27
|
it { expect(subject.changed).to have_key(:key) }
|
25
28
|
it { expect(subject.changed?(:key)).to be_truthy }
|
26
29
|
|
30
|
+
it { expect(subject.inspect).to include 'changed=' }
|
31
|
+
|
27
32
|
context 'with change' do
|
28
33
|
let(:change) { subject.changed.fetch(:key) }
|
29
34
|
|
@@ -37,6 +42,35 @@ module Statefully
|
|
37
42
|
let(:previous) { current }
|
38
43
|
|
39
44
|
it { expect(subject).to be_empty }
|
45
|
+
it { expect(subject.inspect).to eq '#<Statefully::Diff::Unchanged>' }
|
40
46
|
end # context 'when nothing changed'
|
47
|
+
|
48
|
+
shared_examples 'diff_is_empty' do
|
49
|
+
it { expect(subject).to be_empty }
|
50
|
+
it { expect(subject.added).to be_empty }
|
51
|
+
it { expect(subject.changed).to be_empty }
|
52
|
+
end # shared_examples 'diff_is_empty'
|
53
|
+
|
54
|
+
context 'when failed' do
|
55
|
+
let(:error) { RuntimeError.new('boo!') }
|
56
|
+
let(:previous) { State.create }
|
57
|
+
let(:current) { previous.fail(error) }
|
58
|
+
|
59
|
+
it_behaves_like 'diff_is_empty'
|
60
|
+
|
61
|
+
it { expect(subject.error).to eq error }
|
62
|
+
|
63
|
+
it { expect(subject.inspect).to start_with '#<Statefully::Diff::Failed' }
|
64
|
+
it { expect(subject.inspect).to include 'error=#<RuntimeError: boo!>' }
|
65
|
+
end # context 'when failed'
|
66
|
+
|
67
|
+
context 'when finished' do
|
68
|
+
let(:previous) { State.create }
|
69
|
+
let(:current) { previous.finish }
|
70
|
+
|
71
|
+
it_behaves_like 'diff_is_empty'
|
72
|
+
|
73
|
+
it { expect(subject.inspect).to eq '#<Statefully::Diff::Finished>' }
|
74
|
+
end # context 'when finished'
|
41
75
|
end # describe Diff
|
42
76
|
end # module Statefully
|
data/spec/state_spec.rb
CHANGED
@@ -4,7 +4,7 @@ module Statefully
|
|
4
4
|
describe State do
|
5
5
|
describe '.create' do
|
6
6
|
subject { described_class.create(key: 'val') }
|
7
|
-
it { expect(subject).to
|
7
|
+
it { expect(subject).to be_successful }
|
8
8
|
end # describe '.create'
|
9
9
|
end # describe State
|
10
10
|
|
@@ -31,13 +31,19 @@ module Statefully
|
|
31
31
|
|
32
32
|
describe 'trivial readers' do
|
33
33
|
it { expect(subject.resolve).to eq subject }
|
34
|
-
it { expect(subject).to
|
35
|
-
it { expect(subject).not_to
|
34
|
+
it { expect(subject).to be_successful }
|
35
|
+
it { expect(subject).not_to be_failed }
|
36
36
|
it { expect(subject).not_to be_finished }
|
37
37
|
end # describe 'trivial readers'
|
38
38
|
|
39
|
+
describe '#inspect' do
|
40
|
+
let(:expected) { '#<Statefully::State::Success old_key="val">' }
|
41
|
+
|
42
|
+
it { expect(subject.inspect).to eq expected }
|
43
|
+
end # describe '#inspect'
|
44
|
+
|
39
45
|
shared_examples 'successful_state' do
|
40
|
-
it { expect(next_state).to
|
46
|
+
it { expect(next_state).to be_successful }
|
41
47
|
it { expect(next_state.old_key).to eq val }
|
42
48
|
|
43
49
|
it { expect(next_state.previous).to eq subject }
|
@@ -64,11 +70,11 @@ module Statefully
|
|
64
70
|
end # describe '#succeed'
|
65
71
|
|
66
72
|
describe '#fail' do
|
67
|
-
let(:error) { RuntimeError.new('
|
73
|
+
let(:error) { RuntimeError.new('boo!') }
|
68
74
|
let(:next_state) { subject.fail(error) }
|
69
75
|
|
70
|
-
it { expect(next_state).not_to
|
71
|
-
it { expect(next_state).to
|
76
|
+
it { expect(next_state).not_to be_successful }
|
77
|
+
it { expect(next_state).to be_failed }
|
72
78
|
it { expect(next_state).not_to be_finished }
|
73
79
|
it { expect(subject).not_to be_finished }
|
74
80
|
it { expect(next_state.old_key).to eq val }
|
@@ -81,11 +87,19 @@ module Statefully
|
|
81
87
|
end
|
82
88
|
end
|
83
89
|
|
90
|
+
describe '#inspect' do
|
91
|
+
let(:inspect) { next_state.inspect }
|
92
|
+
|
93
|
+
it { expect(inspect).to start_with '#<Statefully::State::Failure' }
|
94
|
+
it { expect(inspect).to include 'old_key="val"' }
|
95
|
+
it { expect(inspect).to include 'error="#<RuntimeError: boo!>"' }
|
96
|
+
end # describe '#inspect'
|
97
|
+
|
84
98
|
context 'with history' do
|
85
99
|
let(:history) { next_state.history }
|
86
100
|
|
87
101
|
it { expect(history.size).to eq 2 }
|
88
|
-
it { expect(history.first).to eq error }
|
102
|
+
it { expect(history.first.error).to eq error }
|
89
103
|
it { expect(history.last.added).to include :old_key }
|
90
104
|
end # context 'with history'
|
91
105
|
end # describe '#fail'
|
@@ -102,7 +116,7 @@ module Statefully
|
|
102
116
|
let(:history) { next_state.history }
|
103
117
|
|
104
118
|
it { expect(history.size).to eq 2 }
|
105
|
-
it { expect(history.first).to eq
|
119
|
+
it { expect(history.first).to eq Diff::Finished.instance }
|
106
120
|
it { expect(history.last.added).to include :old_key }
|
107
121
|
end # context 'with history'
|
108
122
|
end # describe '#finish'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: statefully
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcin Wyszynski
|
@@ -52,6 +52,7 @@ extra_rdoc_files: []
|
|
52
52
|
files:
|
53
53
|
- lib/statefully.rb
|
54
54
|
- lib/statefully/diff.rb
|
55
|
+
- lib/statefully/inspect.rb
|
55
56
|
- lib/statefully/state.rb
|
56
57
|
- spec/diff_spec.rb
|
57
58
|
- spec/spec_helper.rb
|