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 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