mattsnyder-stately 0.2.1
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.
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/.yardopts +4 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +34 -0
- data/MIT-LICENSE +20 -0
- data/README.md +178 -0
- data/Rakefile +38 -0
- data/lib/stately/core_ext.rb +5 -0
- data/lib/stately/machine.rb +26 -0
- data/lib/stately/state.rb +96 -0
- data/lib/stately/version.rb +3 -0
- data/lib/stately.rb +196 -0
- data/lib/tasks/stately_tasks.rake +4 -0
- data/spec/functional/stately_spec.rb +305 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/unit/stately/machine_spec.rb +119 -0
- data/spec/unit/stately/state_spec.rb +101 -0
- data/spec/unit/stately_spec.rb +58 -0
- data/stately.gemspec +23 -0
- metadata +151 -0
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Stately do
|
5
|
+
before do
|
6
|
+
@order_class = Class.new(OpenStruct) do
|
7
|
+
stately :start => :processing do
|
8
|
+
state :completed do
|
9
|
+
prevent_from :refunded
|
10
|
+
|
11
|
+
before_transition :from => :processing, :do => :before_completed
|
12
|
+
before_transition :from => :invalid, :do => :cleanup_invalid
|
13
|
+
after_transition :do => :after_completed
|
14
|
+
|
15
|
+
validate :validates_amount
|
16
|
+
validate :validates_credit_card
|
17
|
+
end
|
18
|
+
|
19
|
+
state :invalid do
|
20
|
+
prevent_from :completed, :refunded
|
21
|
+
end
|
22
|
+
|
23
|
+
state :processing do
|
24
|
+
prevent_from :completed, :invalid, :refunded
|
25
|
+
end
|
26
|
+
|
27
|
+
state :refunded do
|
28
|
+
allow_from :completed
|
29
|
+
|
30
|
+
before_transition :from => :completed, :do => :before_refunded
|
31
|
+
after_transition :from => :completed, :do => :after_refunded
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def before_completed
|
38
|
+
self.serial_number = Time.now.usec
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_completed
|
42
|
+
end
|
43
|
+
|
44
|
+
def before_refunded
|
45
|
+
self.refunded_reason = 'Overcharged'
|
46
|
+
end
|
47
|
+
|
48
|
+
def after_refunded
|
49
|
+
end
|
50
|
+
|
51
|
+
def cleanup_invalid
|
52
|
+
self.serial_number = nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def validates_amount
|
56
|
+
amount > 0.0 && amount < 100.0
|
57
|
+
end
|
58
|
+
|
59
|
+
def validates_credit_card
|
60
|
+
self.cc_number == 123
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.should_call_callbacks_on_complete(order)
|
66
|
+
@order = order
|
67
|
+
|
68
|
+
describe 'callbacks' do
|
69
|
+
it 'calls callbacks in order' do
|
70
|
+
@order.should_receive(:before_completed).ordered
|
71
|
+
@order.should_receive(:after_completed).ordered
|
72
|
+
@order.should_not_receive :cleanup_invalid
|
73
|
+
|
74
|
+
@order.complete
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'sets serial_number' do
|
78
|
+
@order.serial_number.should be_nil
|
79
|
+
@order.complete
|
80
|
+
@order.serial_number.should_not be_nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.should_call_validations_on_complete(order)
|
86
|
+
@order = order
|
87
|
+
|
88
|
+
describe 'validations' do
|
89
|
+
it 'calls validations in order' do
|
90
|
+
@order.should_receive(:validates_amount).ordered
|
91
|
+
@order.should_receive(:validates_credit_card).ordered
|
92
|
+
|
93
|
+
@order.complete
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'return values' do
|
97
|
+
before do
|
98
|
+
@order.stub :validates_amount => false
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should halt on false' do
|
102
|
+
@order.should_receive :validates_amount
|
103
|
+
@order.should_receive :validates_credit_card
|
104
|
+
@order.should_not_receive :before_completed
|
105
|
+
@order.should_not_receive :after_completed
|
106
|
+
@order.should_not_receive :cleanup_invalid
|
107
|
+
|
108
|
+
current_state = @order.state
|
109
|
+
@order.complete
|
110
|
+
@order.state.should == current_state
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.should_prevent_transition(from, to, action)
|
117
|
+
before do
|
118
|
+
@order = @order_class.new(:amount => 99, :cc_number => 123)
|
119
|
+
@order.state = from
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'should be prevented' do
|
123
|
+
lambda { @order.send(action) }.should raise_error(Stately::InvalidTransition,
|
124
|
+
"Prevented transition from #{from} to #{to}.")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.should_set_state(new_state, order, action)
|
129
|
+
@order = order
|
130
|
+
|
131
|
+
describe 'on success' do
|
132
|
+
before do
|
133
|
+
@order.send action
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'sets state' do
|
137
|
+
@order.state.should == new_state
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'initial state' do
|
143
|
+
before do
|
144
|
+
@order = @order_class.new(:amount => 99, :cc_number => 123)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'creates actions for each state' do
|
148
|
+
@order_class.method_defined?(:complete).should be_true
|
149
|
+
@order_class.method_defined?(:process).should be_true
|
150
|
+
@order_class.method_defined?(:refund).should be_true
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'finds all states' do
|
154
|
+
@order.states.should == [:completed, :invalid, :processing, :refunded]
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'sets initial state to processing' do
|
158
|
+
@order.state.should == 'processing'
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#process' do
|
163
|
+
describe 'from processing' do
|
164
|
+
should_prevent_transition('processing', 'processing', :process)
|
165
|
+
end
|
166
|
+
|
167
|
+
describe 'from completed' do
|
168
|
+
should_prevent_transition('completed', 'processing', :process)
|
169
|
+
end
|
170
|
+
|
171
|
+
describe 'from invalid' do
|
172
|
+
should_prevent_transition('invalid', 'processing', :process)
|
173
|
+
end
|
174
|
+
|
175
|
+
describe 'from refunded' do
|
176
|
+
should_prevent_transition('refunded', 'processing', :process)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe '#complete' do
|
181
|
+
before do
|
182
|
+
@order = @order_class.new(:amount => 99, :cc_number => 123)
|
183
|
+
end
|
184
|
+
|
185
|
+
describe 'from processing' do
|
186
|
+
should_call_validations_on_complete(@order)
|
187
|
+
|
188
|
+
describe 'callbacks' do
|
189
|
+
it 'calls callbacks in order' do
|
190
|
+
@order.should_receive(:before_completed).ordered
|
191
|
+
@order.should_receive(:after_completed).ordered
|
192
|
+
@order.should_not_receive :cleanup_invalid
|
193
|
+
|
194
|
+
@order.complete
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'sets serial_number' do
|
198
|
+
@order.serial_number.should be_nil
|
199
|
+
@order.complete
|
200
|
+
@order.serial_number.should_not be_nil
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
should_set_state('completed', @order, :complete)
|
205
|
+
end
|
206
|
+
|
207
|
+
describe 'from completed' do
|
208
|
+
should_prevent_transition('completed', 'completed', :complete)
|
209
|
+
end
|
210
|
+
|
211
|
+
describe 'from invalid' do
|
212
|
+
before do
|
213
|
+
@order.serial_number = Time.now.usec
|
214
|
+
@order.state = 'invalid'
|
215
|
+
end
|
216
|
+
|
217
|
+
should_call_validations_on_complete(@order)
|
218
|
+
|
219
|
+
describe 'callbacks' do
|
220
|
+
it 'calls callbacks in order' do
|
221
|
+
@order.should_receive(:cleanup_invalid).ordered
|
222
|
+
@order.should_receive(:after_completed).ordered
|
223
|
+
@order.should_not_receive :before_completed
|
224
|
+
|
225
|
+
@order.complete
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'sets serial_number to nil' do
|
229
|
+
@order.serial_number.should_not be_nil
|
230
|
+
@order.complete
|
231
|
+
@order.serial_number.should be_nil
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
should_set_state('completed', @order, :complete)
|
236
|
+
end
|
237
|
+
|
238
|
+
describe 'from refunded' do
|
239
|
+
should_prevent_transition('refunded', 'completed', :complete)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe '#invalidate' do
|
244
|
+
describe 'from processing' do
|
245
|
+
before do
|
246
|
+
@order = @order_class.new(:amount => 99, :cc_number => 123)
|
247
|
+
@order.invalidate
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'sets state' do
|
251
|
+
@order.state.should == 'invalid'
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe 'from completed' do
|
256
|
+
should_prevent_transition('completed', 'invalid', :invalidate)
|
257
|
+
end
|
258
|
+
|
259
|
+
describe 'from invalid' do
|
260
|
+
should_prevent_transition('invalid', 'invalid', :invalidate)
|
261
|
+
end
|
262
|
+
|
263
|
+
describe 'from refunded' do
|
264
|
+
should_prevent_transition('refunded', 'invalid', :invalidate)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
describe '#refund' do
|
269
|
+
describe 'from processing' do
|
270
|
+
should_prevent_transition('processing', 'refunded', :refund)
|
271
|
+
end
|
272
|
+
|
273
|
+
describe 'from completed' do
|
274
|
+
before do
|
275
|
+
@order = @order_class.new(:amount => 99, :cc_number => 123)
|
276
|
+
@order.state = 'completed'
|
277
|
+
end
|
278
|
+
|
279
|
+
describe 'callbacks' do
|
280
|
+
it 'calls callbacks in order' do
|
281
|
+
@order.should_receive(:before_refunded).ordered
|
282
|
+
@order.should_receive(:after_refunded).ordered
|
283
|
+
|
284
|
+
@order.refund
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'sets refunded_reason' do
|
288
|
+
@order.refunded_reason.should be_nil
|
289
|
+
@order.refund
|
290
|
+
@order.refunded_reason.should_not be_nil
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
should_set_state('refunded', @order, :refund)
|
295
|
+
end
|
296
|
+
|
297
|
+
describe 'from invalid' do
|
298
|
+
should_prevent_transition('invalid', 'refunded', :refund)
|
299
|
+
end
|
300
|
+
|
301
|
+
describe 'from refunded' do
|
302
|
+
should_prevent_transition('refunded', 'refunded', :refund)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stately::Machine do
|
4
|
+
before do
|
5
|
+
@machine = Stately::Machine.new(:state, :processing)
|
6
|
+
end
|
7
|
+
|
8
|
+
describe 'initialize' do
|
9
|
+
it 'sets initial vars' do
|
10
|
+
@machine.start.should == :processing
|
11
|
+
@machine.state_attr.should == :state
|
12
|
+
@machine.states.map(&:to_s).should == ['processing']
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'guesses the initial action' do
|
16
|
+
@machine.states.first.action.should == 'process'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#state' do
|
21
|
+
describe 'with name only' do
|
22
|
+
describe 'of a new state' do
|
23
|
+
before do
|
24
|
+
@machine.state(:completed)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'adds a new state' do
|
28
|
+
@machine.states.map(&:to_s).should == ['processing', 'completed']
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'of a previously defined state' do
|
33
|
+
before do
|
34
|
+
@machine.state(:processing)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "doesn't add a new state" do
|
38
|
+
@machine.states.map(&:to_s).should == ['processing']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'with name and action' do
|
44
|
+
describe 'of a new state' do
|
45
|
+
before do
|
46
|
+
@machine.state(:new_state, :action => :transition_to_new_state)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'adds a new state' do
|
50
|
+
@machine.states.map(&:to_s).should == ['processing', 'new_state']
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'adds the correct action to the new state' do
|
54
|
+
@machine.states.last.action.should == 'transition_to_new_state'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'of a previously defined state' do
|
59
|
+
before do
|
60
|
+
@machine.state(:processing, :action => :transition_to_processing)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "doesn't add a new state" do
|
64
|
+
@machine.states.map(&:to_s).should == ['processing']
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'adds the correct action to the existing state' do
|
68
|
+
@machine.states.first.action.should == 'transition_to_processing'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'with name, action, and block' do
|
74
|
+
describe 'of a new state' do
|
75
|
+
before do
|
76
|
+
@machine.state(:new_state, :action => :transition_to_new_state) do
|
77
|
+
allow_from :completed
|
78
|
+
end
|
79
|
+
|
80
|
+
@new_state = @machine.states.last
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'adds a new state' do
|
84
|
+
@machine.states.map(&:to_s).should == ['processing', 'new_state']
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'adds the correct action to the new state' do
|
88
|
+
@new_state.action.should == 'transition_to_new_state'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'includes the allow_from param' do
|
92
|
+
@new_state.allow_from_states.should == [:completed]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'of a previously defined state' do
|
97
|
+
before do
|
98
|
+
@machine.state(:processing, :action => :transition_to_processing) do
|
99
|
+
allow_from :completed
|
100
|
+
end
|
101
|
+
|
102
|
+
@new_state = @machine.states.last
|
103
|
+
end
|
104
|
+
|
105
|
+
it "doesn't add a new state" do
|
106
|
+
@machine.states.map(&:to_s).should == ['processing']
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'adds the correct action to the new state' do
|
110
|
+
@new_state.action.should == 'transition_to_processing'
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'includes the allow_from param' do
|
114
|
+
@new_state.allow_from_states.should == [:completed]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stately::State do
|
4
|
+
describe 'initialize' do
|
5
|
+
describe 'with a block given' do
|
6
|
+
describe 'new' do
|
7
|
+
before do
|
8
|
+
@state = Stately::State.new(:invalid, nil) do
|
9
|
+
allow_from :completed
|
10
|
+
prevent_from :completed, :refunded
|
11
|
+
|
12
|
+
before_transition :do => :prepare
|
13
|
+
before_transition :from => :processing, :do => :before_completed
|
14
|
+
after_transition :do => :cleanup
|
15
|
+
after_transition :from => :processing, :do => :after_processing
|
16
|
+
|
17
|
+
validate :validates_amount
|
18
|
+
validate :validates_credit_card
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should set initial values' do
|
23
|
+
@state.name.should == :invalid
|
24
|
+
|
25
|
+
@state.allow_from_states.should == [:completed]
|
26
|
+
@state.prevent_from_states.should == [:completed, :refunded]
|
27
|
+
|
28
|
+
@state.before_transitions.should == [{:do => :prepare}, {:from => :processing,
|
29
|
+
:do => :before_completed}]
|
30
|
+
@state.after_transitions.should == [{:do => :cleanup}, {:from => :processing,
|
31
|
+
:do => :after_processing}]
|
32
|
+
@state.validations.should == [:validates_amount, :validates_credit_card]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'without a block given' do
|
38
|
+
describe 'new' do
|
39
|
+
before do
|
40
|
+
@state = Stately::State.new(:test_state)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should set initial values' do
|
44
|
+
@state.name.should == :test_state
|
45
|
+
|
46
|
+
@state.allow_from_states.should == []
|
47
|
+
@state.prevent_from_states.should == []
|
48
|
+
|
49
|
+
@state.before_transitions.should == []
|
50
|
+
@state.after_transitions.should == []
|
51
|
+
@state.validations.should == []
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'with a given action' do
|
56
|
+
before do
|
57
|
+
@state = Stately::State.new(:test_state, :test_action)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should set the given action name' do
|
61
|
+
@state.action.should == 'test_action'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'without a given action' do
|
66
|
+
before do
|
67
|
+
@actions = { :completed => :complete, :converting => :convert, :invalid => :invalidate,
|
68
|
+
:preparing => :prepare, :processing => :process, :refunded => :refund, :reticulating => :reticulate,
|
69
|
+
:saving => :save, :searching => :search, :started => :start, :stopped => :stop }
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should set the correct action verb' do
|
73
|
+
@actions.map do |state_name, action_name|
|
74
|
+
state = Stately::State.new(state_name)
|
75
|
+
state.action.should == action_name.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#to_s' do
|
83
|
+
before do
|
84
|
+
@state = Stately::State.new(:test_state)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'should return a string' do
|
88
|
+
@state.to_s.should == 'test_state'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#to_sym' do
|
93
|
+
before do
|
94
|
+
@state = Stately::State.new('test_state')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should return a symbol' do
|
98
|
+
@state.to_sym.should == :test_state
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Stately::InstanceMethods do
|
5
|
+
before do
|
6
|
+
@test_class = Class.new(Object) do
|
7
|
+
attr_accessor :state
|
8
|
+
|
9
|
+
stately :start => :processing do
|
10
|
+
state :completed
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
@object = @test_class.new
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'initialize' do
|
18
|
+
it 'creates a new Stately::Machine' do
|
19
|
+
@object.stately_machine.class.should == Stately::Machine
|
20
|
+
@object.stately_machine.should == @test_class.stately_machine
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'sets initial state' do
|
24
|
+
@object.state.should == 'processing'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#states' do
|
29
|
+
it 'returns known state names in order' do
|
30
|
+
@object.states.should == [:processing, :completed]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'actions' do
|
35
|
+
it 'defines action methods' do
|
36
|
+
@test_class.method_defined?(:complete).should be_true
|
37
|
+
@test_class.method_defined?(:process).should be_true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe 'stately_machine' do
|
42
|
+
it 'defines a class-level accessor called stately_machine' do
|
43
|
+
@test_class.respond_to?(:stately_machine).should be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'defines an instance-level accessor called stately_machine' do
|
47
|
+
@test_class.method_defined?(:stately_machine).should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'defines a class-level setter called stately_machine=' do
|
51
|
+
@test_class.respond_to?(:stately_machine=).should be_true
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'defines an instance-level setter called stately_machine=' do
|
55
|
+
@test_class.method_defined?(:stately_machine=).should be_true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/stately.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path('../lib', __FILE__)
|
2
|
+
require 'stately/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'mattsnyder-stately'
|
6
|
+
s.version = Stately::VERSION
|
7
|
+
s.authors = ['Ryan Twomey']
|
8
|
+
s.email = ['rtwomey@gmail.com']
|
9
|
+
s.homepage = 'http://github.com/rtwomey/stately'
|
10
|
+
s.summary = 'A simple, elegant state machine for Ruby'
|
11
|
+
s.description = 'Add an elegant state machine to your ruby objects with a simple DSL'
|
12
|
+
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
15
|
+
|
16
|
+
s.add_development_dependency 'redcarpet', '~> 2.2.2'
|
17
|
+
s.add_development_dependency 'rspec', '~> 2.0'
|
18
|
+
s.add_development_dependency 'yard', '~> 0.8.3'
|
19
|
+
s.add_development_dependency 'rdoc'
|
20
|
+
|
21
|
+
s.required_ruby_version = Gem::Requirement.new('>= 1.8.7')
|
22
|
+
s.require_paths = ['lib']
|
23
|
+
end
|