statefully 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1962b427e73969e2c630c8fe1c22a0f55e7f2fc4
4
- data.tar.gz: 3f5b532398769ecdaeaeb897368230022d22825a
3
+ metadata.gz: 97acdf9e907dd51ad5227ef53828030d0943d35d
4
+ data.tar.gz: 3d9564c5fa59479e584e38c94ebdf504e1e1894d
5
5
  SHA512:
6
- metadata.gz: e0189ab5e902b110f36e6189d7c81b88a8b53a99c2015bec935cf54cafb2fcc71747810247297acd609b0d1517a6440b89f821b0d4f853d18632768470400358
7
- data.tar.gz: df202b95fe53c904ebb4d2235a759622e6583ee674eca303274b1685f91782af247f82b50b1ffe47fb33d25618d7da3d684c41a99c8906a311f178442edc034a
6
+ metadata.gz: 94467d76d84d115d674c84db44022a6c4e76d81e417b1ca48eb613734802fd80c420f4a79832aa248f1622e9260c26d1bdfb8c72f9c73f078a14df230cde96b5
7
+ data.tar.gz: 732e6d9e831787099ae318d706a0c6d95280ea8ee06217e1bc0b3f9a30bd058d150b8053a972ffd631a626e3e75937cac403a5fc9e14609f0413f870e6da9894
@@ -2,52 +2,55 @@ require 'set'
2
2
  require 'singleton'
3
3
 
4
4
  module Statefully
5
- class Diff
6
- attr_reader :added, :changed
7
-
8
- def self.create(current, previous)
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? ? None.instance : new(**changes).freeze
10
+ changes.empty? ? Unchanged.instance : Changed.new(**changes).freeze
11
11
  end
12
+ module_function :create
12
13
 
13
- def empty?
14
- false
15
- end
14
+ class Changed
15
+ attr_reader :added, :changed
16
16
 
17
- def inspect
18
- "<#{self.class.name} #{inspect_details}>"
19
- end
17
+ def empty?
18
+ false
19
+ end
20
20
 
21
- def added?(key)
22
- added.key?(key)
23
- end
21
+ def inspect
22
+ "#<#{self.class.name} #{inspect_details}>"
23
+ end
24
24
 
25
- def changed?(key)
26
- changed.key?(key)
27
- end
25
+ def added?(key)
26
+ added.key?(key)
27
+ end
28
28
 
29
- private
29
+ def changed?(key)
30
+ changed.key?(key)
31
+ end
30
32
 
31
- def inspect_details
32
- [inspect_added, inspect_changed].compact.join(', ')
33
- end
33
+ private
34
34
 
35
- def inspect_added
36
- added.empty? ? nil : "added=#{Inspect.from_hash(added)}"
37
- end
35
+ def inspect_details
36
+ [inspect_added, inspect_changed].compact.join(', ')
37
+ end
38
38
 
39
- def inspect_changed
40
- changed.empty? ? nil : "changed=#{Inspect.from_hash(changed)}"
41
- end
39
+ def inspect_added
40
+ added.empty? ? nil : "added=#{Inspect.from_hash(added)}"
41
+ end
42
42
 
43
- def initialize(added:, changed:)
44
- @added = added.freeze
45
- @changed = changed.freeze
46
- end
43
+ def inspect_changed
44
+ changed.empty? ? nil : "changed=#{Inspect.from_hash(changed)}"
45
+ end
47
46
 
48
- class None
49
- include Singleton
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
- "<#{self.class.name}>"
73
+ "#<#{self.class.name}>"
65
74
  end
66
- end # class None
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 # class Diff
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
@@ -21,12 +21,12 @@ module Statefully
21
21
  ([diff] + previous.history).freeze
22
22
  end
23
23
 
24
- def success?
24
+ def successful?
25
25
  true
26
26
  end
27
27
 
28
- def failure?
29
- !success?
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 success?
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
- :finished
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
@@ -1,2 +1,3 @@
1
1
  require 'statefully/diff'
2
+ require 'statefully/inspect'
2
3
  require 'statefully/state'
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 be_success }
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 be_success }
35
- it { expect(subject).not_to be_failure }
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 be_success }
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('snakes on a plane') }
73
+ let(:error) { RuntimeError.new('boo!') }
68
74
  let(:next_state) { subject.fail(error) }
69
75
 
70
- it { expect(next_state).not_to be_success }
71
- it { expect(next_state).to be_failure }
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 :finished }
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.2
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