aasm 3.1.0 → 3.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +13 -7
- data/CHANGELOG.md +13 -0
- data/Gemfile +2 -1
- data/README.md +25 -8
- data/aasm.gemspec +1 -1
- data/gemfiles/rails_3.2.gemfile +2 -1
- data/gemfiles/rails_4.0.gemfile +6 -1
- data/gemfiles/rails_4.1.gemfile +7 -2
- data/lib/aasm/aasm.rb +1 -1
- data/lib/aasm/base.rb +10 -11
- data/lib/aasm/event.rb +1 -1
- data/lib/aasm/instance_base.rb +5 -2
- data/lib/aasm/localizer.rb +1 -1
- data/lib/aasm/persistence/base.rb +9 -9
- data/lib/aasm/persistence/sequel_persistence.rb +108 -0
- data/lib/aasm/persistence.rb +3 -0
- data/lib/aasm/state.rb +3 -3
- data/lib/aasm/state_machine.rb +14 -10
- data/lib/aasm/version.rb +1 -1
- data/spec/unit/complex_example_spec.rb +9 -0
- data/spec/unit/event_spec.rb +17 -0
- data/spec/unit/memory_leak_spec.rb +2 -2
- data/spec/unit/persistence/mongoid_persistance_spec.rb +1 -1
- data/spec/unit/persistence/sequel_persistence_spec.rb +103 -0
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3953eaa965802447de8e3783a35c91dcc89e87a4
|
|
4
|
+
data.tar.gz: 1b70e517fc29f1fad325a0a46d126cab2eebf029
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 220319a5169ac9f1928a5beaaacf81c72d47ab3cf972dea079633fcc82ac8bfa3d42c97c0ffa38b9526e1a50b729ba331cc7ae29a1267dddd4d3e9ae52a7cd70
|
|
7
|
+
data.tar.gz: 0eff6b102e298af64e76e6f71cff21989d260c626efada6ed5dc763d092d351fac20a9696f1882ab8110e535b20897def8c5c7d2c013d7df82e4b6c437590a2f
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
|
@@ -5,7 +5,7 @@ rvm:
|
|
|
5
5
|
- 1.9.2
|
|
6
6
|
- 1.9.3
|
|
7
7
|
- 2.0.0
|
|
8
|
-
- 2.1
|
|
8
|
+
- 2.1
|
|
9
9
|
# - jruby-18mode # JRuby in 1.8 mode
|
|
10
10
|
- jruby-19mode # JRuby in 1.9 mode
|
|
11
11
|
- rbx-2.2.1
|
|
@@ -22,9 +22,15 @@ matrix:
|
|
|
22
22
|
- rvm: rbx-2.2.1
|
|
23
23
|
- rvm: jruby-19mode
|
|
24
24
|
exclude:
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
25
|
+
- rvm: 1.8.7
|
|
26
|
+
gemfile: gemfiles/rails_4.0.gemfile
|
|
27
|
+
- rvm: 1.8.7
|
|
28
|
+
gemfile: gemfiles/rails_4.1.gemfile
|
|
29
|
+
- rvm: 1.9.2
|
|
30
|
+
gemfile: gemfiles/rails_4.0.gemfile
|
|
31
|
+
- rvm: 1.9.2
|
|
32
|
+
gemfile: gemfiles/rails_4.1.gemfile
|
|
33
|
+
- rvm: 1.9.3
|
|
34
|
+
gemfile: gemfiles/rails_4.1.gemfile
|
|
35
|
+
- rvm: jruby-19mode
|
|
36
|
+
gemfile: gemfiles/rails_4.1.gemfile
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@
|
|
|
4
4
|
|
|
5
5
|
* deprecated old aasm_* class methods (old-style DSL), in preparation for AASM v4.0.0
|
|
6
6
|
|
|
7
|
+
## 3.2.1
|
|
8
|
+
|
|
9
|
+
* bugfix: permissible_events and events did not contain events with an empty "from" transition (see [issue #140](https://github.com/aasm/aasm/issues/140) and [issue #141](https://github.com/aasm/aasm/issues/141), thanks to [@daniel-rikowski](https://github.com/daniel-rikowski))
|
|
10
|
+
|
|
11
|
+
## 3.2.0
|
|
12
|
+
|
|
13
|
+
* support [Sequel](http://sequel.jeremyevans.net/) (see [issue #119](https://github.com/aasm/aasm/issues/119), thanks to [@godfat](https://github.com/godfat))
|
|
14
|
+
* may not fire an unknown event (see [issue #128](https://github.com/aasm/aasm/issues/128)
|
|
15
|
+
|
|
16
|
+
## 3.1.1
|
|
17
|
+
|
|
18
|
+
* bugfix: don't require ActiveRecord for localizing AASM event and state name (see [issue #113](https://github.com/aasm/aasm/issues/113), thanks to [@silentshade](https://github.com/silentshade))
|
|
19
|
+
|
|
7
20
|
## 3.1.0
|
|
8
21
|
|
|
9
22
|
* validating the current state (see [issue #95](https://github.com/aasm/aasm/issues/95), thanks to [@ivantsepp](https://github.com/ivantsepp))
|
data/Gemfile
CHANGED
|
@@ -5,7 +5,8 @@ gem "coveralls", :platforms => :ruby
|
|
|
5
5
|
gem 'rubysl', :platforms => :rbx
|
|
6
6
|
gem "jruby-openssl", :platforms => :jruby
|
|
7
7
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
|
8
|
-
gem "rails", "3.2.
|
|
8
|
+
gem "rails", "3.2.18"
|
|
9
9
|
gem 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
10
|
+
gem 'sequel'
|
|
10
11
|
|
|
11
12
|
gemspec
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AASM - Ruby state machines
|
|
2
2
|
|
|
3
3
|
<a href="http://badge.fury.io/rb/aasm"><img src="https://badge.fury.io/rb/aasm@2x.png" alt="Gem Version" height="18"></a>
|
|
4
|
-
[](https://travis-ci.org/aasm/aasm)
|
|
5
5
|
[](https://codeclimate.com/github/aasm/aasm)
|
|
6
6
|
[](https://coveralls.io/r/aasm/aasm)
|
|
7
7
|
|
|
@@ -278,6 +278,23 @@ class Job < ActiveRecord::Base
|
|
|
278
278
|
end
|
|
279
279
|
```
|
|
280
280
|
|
|
281
|
+
### Sequel
|
|
282
|
+
|
|
283
|
+
AASM also supports [Sequel](http://sequel.jeremyevans.net/) besides _ActiveRecord_ and _Mongoid_.
|
|
284
|
+
|
|
285
|
+
```ruby
|
|
286
|
+
class Job < Sequel::Model
|
|
287
|
+
include AASM
|
|
288
|
+
|
|
289
|
+
aasm do # default column: aasm_state
|
|
290
|
+
...
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
However it's not yet as feature complete as _ActiveRecord_. For example, there are
|
|
296
|
+
scopes defined yet. See [Automatic Scopes](#automatic-scopes).
|
|
297
|
+
|
|
281
298
|
### Mongoid
|
|
282
299
|
|
|
283
300
|
AASM also supports persistence to Mongodb if you're using Mongoid. Make sure
|
|
@@ -308,7 +325,7 @@ class Job < ActiveRecord::Base
|
|
|
308
325
|
state :cleaning
|
|
309
326
|
end
|
|
310
327
|
|
|
311
|
-
def sleeping
|
|
328
|
+
def self.sleeping
|
|
312
329
|
"This method name is in already use"
|
|
313
330
|
end
|
|
314
331
|
end
|
|
@@ -317,10 +334,10 @@ end
|
|
|
317
334
|
```ruby
|
|
318
335
|
class JobsController < ApplicationController
|
|
319
336
|
def index
|
|
320
|
-
@running_jobs =
|
|
321
|
-
@recent_cleaning_jobs =
|
|
337
|
+
@running_jobs = Job.running
|
|
338
|
+
@recent_cleaning_jobs = Job.cleaning.where('created_at >= ?', 3.days.ago)
|
|
322
339
|
|
|
323
|
-
# @sleeping_jobs =
|
|
340
|
+
# @sleeping_jobs = Job.sleeping #=> "This method name is in already use"
|
|
324
341
|
end
|
|
325
342
|
end
|
|
326
343
|
```
|
|
@@ -431,13 +448,13 @@ Given the `Job` class from above:
|
|
|
431
448
|
```ruby
|
|
432
449
|
job = Job.new
|
|
433
450
|
|
|
434
|
-
job.aasm.states
|
|
451
|
+
job.aasm.states.map(&:name)
|
|
435
452
|
=> [:sleeping, :running, :cleaning]
|
|
436
453
|
|
|
437
|
-
job.aasm.states(:permissible => true)
|
|
454
|
+
job.aasm.states(:permissible => true).map(&:name)
|
|
438
455
|
=> [:running]
|
|
439
456
|
job.run
|
|
440
|
-
job.aasm.states(:permissible => true)
|
|
457
|
+
job.aasm.states(:permissible => true).map(&:name)
|
|
441
458
|
=> [:cleaning, :sleeping]
|
|
442
459
|
|
|
443
460
|
job.aasm.events
|
data/aasm.gemspec
CHANGED
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
|
19
19
|
# s.add_development_dependency 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
20
20
|
s.add_development_dependency 'rake'
|
|
21
21
|
s.add_development_dependency 'sdoc'
|
|
22
|
-
s.add_development_dependency 'rspec', '
|
|
22
|
+
s.add_development_dependency 'rspec', '~> 2.14'
|
|
23
23
|
s.add_development_dependency 'rr'
|
|
24
24
|
# s.add_development_dependency 'sqlite3'
|
|
25
25
|
s.add_development_dependency 'minitest'
|
data/gemfiles/rails_3.2.gemfile
CHANGED
|
@@ -6,7 +6,8 @@ gem 'rubysl', :platforms => :rbx
|
|
|
6
6
|
gem 'rubinius-developer_tools', :platforms => :rbx
|
|
7
7
|
gem "jruby-openssl", :platforms => :jruby
|
|
8
8
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
|
9
|
-
gem "rails", "3.2.
|
|
9
|
+
gem "rails", "3.2.18"
|
|
10
10
|
gem 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
11
|
+
gem 'sequel'
|
|
11
12
|
|
|
12
13
|
gemspec :path => "../"
|
data/gemfiles/rails_4.0.gemfile
CHANGED
|
@@ -6,6 +6,11 @@ gem 'rubysl', :platforms => :rbx
|
|
|
6
6
|
gem 'rubinius-developer_tools', :platforms => :rbx
|
|
7
7
|
gem "jruby-openssl", :platforms => :jruby
|
|
8
8
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
|
9
|
-
gem "rails", "4.0.
|
|
9
|
+
gem "rails", "4.0.5"
|
|
10
|
+
|
|
11
|
+
# mongoid is not yet compatible with Rails >= 4
|
|
12
|
+
# gem 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
13
|
+
|
|
14
|
+
gem 'sequel'
|
|
10
15
|
|
|
11
16
|
gemspec :path => "../"
|
data/gemfiles/rails_4.1.gemfile
CHANGED
|
@@ -6,6 +6,11 @@ gem 'rubysl', :platforms => :rbx
|
|
|
6
6
|
gem 'rubinius-developer_tools', :platforms => :rbx
|
|
7
7
|
gem "jruby-openssl", :platforms => :jruby
|
|
8
8
|
gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
|
|
9
|
-
gem "rails", "4.1.
|
|
9
|
+
gem "rails", "4.1.1"
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
# mongoid is not yet compatible with Rails >= 4
|
|
12
|
+
# gem 'mongoid' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
|
|
13
|
+
|
|
14
|
+
gem 'sequel'
|
|
15
|
+
|
|
16
|
+
gemspec :path => "../"
|
data/lib/aasm/aasm.rb
CHANGED
|
@@ -5,7 +5,7 @@ module AASM
|
|
|
5
5
|
|
|
6
6
|
# do not overwrite existing state machines, which could have been created by
|
|
7
7
|
# inheritance, see class method inherited
|
|
8
|
-
AASM::StateMachine[base] ||= AASM::StateMachine.new
|
|
8
|
+
AASM::StateMachine[base] ||= AASM::StateMachine.new
|
|
9
9
|
|
|
10
10
|
AASM::Persistence.load_persistence(base)
|
|
11
11
|
super
|
data/lib/aasm/base.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
module AASM
|
|
2
2
|
class Base
|
|
3
3
|
|
|
4
|
-
def initialize(
|
|
5
|
-
@
|
|
6
|
-
@state_machine = AASM::StateMachine[@
|
|
4
|
+
def initialize(klass, options={}, &block)
|
|
5
|
+
@klass = klass
|
|
6
|
+
@state_machine = AASM::StateMachine[@klass]
|
|
7
7
|
@state_machine.config.column = options[:column].to_sym if options[:column]
|
|
8
8
|
@options = options
|
|
9
9
|
|
|
@@ -30,15 +30,14 @@ module AASM
|
|
|
30
30
|
|
|
31
31
|
# define a state
|
|
32
32
|
def state(name, options={})
|
|
33
|
-
@state_machine.add_state(name, @
|
|
34
|
-
@state_machine.initial_state = name if options[:initial] || !@state_machine.initial_state
|
|
33
|
+
@state_machine.add_state(name, @klass, options)
|
|
35
34
|
|
|
36
|
-
@
|
|
35
|
+
@klass.send(:define_method, "#{name.to_s}?") do
|
|
37
36
|
aasm.current_state == name
|
|
38
37
|
end
|
|
39
38
|
|
|
40
|
-
unless @
|
|
41
|
-
@
|
|
39
|
+
unless @klass.const_defined?("STATE_#{name.to_s.upcase}")
|
|
40
|
+
@klass.const_set("STATE_#{name.to_s.upcase}", name)
|
|
42
41
|
end
|
|
43
42
|
end
|
|
44
43
|
|
|
@@ -49,15 +48,15 @@ module AASM
|
|
|
49
48
|
# an addition over standard aasm so that, before firing an event, you can ask
|
|
50
49
|
# may_event? and get back a boolean that tells you whether the guard method
|
|
51
50
|
# on the transition will let this happen.
|
|
52
|
-
@
|
|
51
|
+
@klass.send(:define_method, "may_#{name.to_s}?") do |*args|
|
|
53
52
|
aasm.may_fire_event?(name, *args)
|
|
54
53
|
end
|
|
55
54
|
|
|
56
|
-
@
|
|
55
|
+
@klass.send(:define_method, "#{name.to_s}!") do |*args, &block|
|
|
57
56
|
aasm_fire_event(name, {:persist => true}, *args, &block)
|
|
58
57
|
end
|
|
59
58
|
|
|
60
|
-
@
|
|
59
|
+
@klass.send(:define_method, "#{name.to_s}") do |*args, &block|
|
|
61
60
|
aasm_fire_event(name, {:persist => false}, *args, &block)
|
|
62
61
|
end
|
|
63
62
|
end
|
data/lib/aasm/event.rb
CHANGED
data/lib/aasm/instance_base.rb
CHANGED
|
@@ -75,8 +75,11 @@ module AASM
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def may_fire_event?(name, *args)
|
|
78
|
-
event = @instance.class.aasm.events[name]
|
|
79
|
-
|
|
78
|
+
if event = @instance.class.aasm.events[name]
|
|
79
|
+
event.may_fire?(@instance, *args)
|
|
80
|
+
else
|
|
81
|
+
false # unknown event
|
|
82
|
+
end
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
def set_current_state_with_persistence(state)
|
data/lib/aasm/localizer.rb
CHANGED
|
@@ -47,7 +47,7 @@ module AASM
|
|
|
47
47
|
|
|
48
48
|
def ancestors_list(klass)
|
|
49
49
|
klass.ancestors.select do |ancestor|
|
|
50
|
-
ancestor.respond_to?(:model_name) unless ancestor == ActiveRecord::Base
|
|
50
|
+
ancestor.respond_to?(:model_name) unless ancestor.name == 'ActiveRecord::Base'
|
|
51
51
|
end
|
|
52
52
|
end
|
|
53
53
|
end
|
|
@@ -87,26 +87,26 @@ module AASM
|
|
|
87
87
|
# make sure to create a (named) scope for each state
|
|
88
88
|
def state_with_scope(name, *args)
|
|
89
89
|
state_without_scope(name, *args)
|
|
90
|
-
if AASM::StateMachine[@
|
|
91
|
-
if @
|
|
90
|
+
if AASM::StateMachine[@klass].config.create_scopes && !@klass.respond_to?(name)
|
|
91
|
+
if @klass.ancestors.map {|klass| klass.to_s}.include?("ActiveRecord::Base")
|
|
92
92
|
|
|
93
|
-
conditions = {"#{@
|
|
93
|
+
conditions = {"#{@klass.table_name}.#{@klass.aasm_column}" => name.to_s}
|
|
94
94
|
if ActiveRecord::VERSION::MAJOR >= 4
|
|
95
|
-
@
|
|
95
|
+
@klass.class_eval do
|
|
96
96
|
scope name, lambda { where(conditions) }
|
|
97
97
|
end
|
|
98
98
|
elsif ActiveRecord::VERSION::MAJOR >= 3
|
|
99
|
-
@
|
|
99
|
+
@klass.class_eval do
|
|
100
100
|
scope name, where(conditions)
|
|
101
101
|
end
|
|
102
102
|
else
|
|
103
|
-
@
|
|
103
|
+
@klass.class_eval do
|
|
104
104
|
named_scope name, :conditions => conditions
|
|
105
105
|
end
|
|
106
106
|
end
|
|
107
|
-
elsif @
|
|
108
|
-
scope_options = lambda { @
|
|
109
|
-
@
|
|
107
|
+
elsif @klass.ancestors.map {|klass| klass.to_s}.include?("Mongoid::Document")
|
|
108
|
+
scope_options = lambda { @klass.send(:where, {@klass.aasm_column.to_sym => name.to_s}) }
|
|
109
|
+
@klass.send(:scope, name, scope_options)
|
|
110
110
|
end
|
|
111
111
|
end
|
|
112
112
|
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module AASM
|
|
2
|
+
module Persistence
|
|
3
|
+
module SequelPersistence
|
|
4
|
+
def self.included(base)
|
|
5
|
+
base.send(:include, AASM::Persistence::Base)
|
|
6
|
+
base.send(:include, AASM::Persistence::SequelPersistence::InstanceMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module InstanceMethods
|
|
10
|
+
def before_validation
|
|
11
|
+
aasm_ensure_initial_state
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def before_create
|
|
16
|
+
aasm_ensure_initial_state
|
|
17
|
+
super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the value of the aasm_column - called from <tt>aasm.current_state</tt>
|
|
21
|
+
#
|
|
22
|
+
# If it's a new record, and the aasm state column is blank it returns the initial state
|
|
23
|
+
#
|
|
24
|
+
# class Foo < Sequel::Model
|
|
25
|
+
# include AASM
|
|
26
|
+
# aasm :column => :status do
|
|
27
|
+
# state :opened
|
|
28
|
+
# state :closed
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# foo = Foo.new
|
|
33
|
+
# foo.current_state # => :opened
|
|
34
|
+
# foo.close
|
|
35
|
+
# foo.current_state # => :closed
|
|
36
|
+
#
|
|
37
|
+
# foo = Foo[1]
|
|
38
|
+
# foo.current_state # => :opened
|
|
39
|
+
# foo.aasm_state = nil
|
|
40
|
+
# foo.current_state # => nil
|
|
41
|
+
#
|
|
42
|
+
# NOTE: intended to be called from an event
|
|
43
|
+
#
|
|
44
|
+
# This allows for nil aasm states - be sure to add validation to your model
|
|
45
|
+
def aasm_read_state
|
|
46
|
+
state = send(self.class.aasm_column)
|
|
47
|
+
if new? && state.to_s.strip.empty?
|
|
48
|
+
aasm.determine_state_name(self.class.aasm.initial_state)
|
|
49
|
+
elsif state.nil?
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
state.to_sym
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Ensures that if the aasm_state column is nil and the record is new
|
|
57
|
+
# that the initial state gets populated before validation on create
|
|
58
|
+
#
|
|
59
|
+
# foo = Foo.new
|
|
60
|
+
# foo.aasm_state # => nil
|
|
61
|
+
# foo.valid?
|
|
62
|
+
# foo.aasm_state # => "open" (where :open is the initial state)
|
|
63
|
+
#
|
|
64
|
+
#
|
|
65
|
+
# foo = Foo.find(:first)
|
|
66
|
+
# foo.aasm_state # => 1
|
|
67
|
+
# foo.aasm_state = nil
|
|
68
|
+
# foo.valid?
|
|
69
|
+
# foo.aasm_state # => nil
|
|
70
|
+
#
|
|
71
|
+
def aasm_ensure_initial_state
|
|
72
|
+
aasm.enter_initial_state if
|
|
73
|
+
send(self.class.aasm_column).to_s.strip.empty?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Writes <tt>state</tt> to the state column and persists it to the database
|
|
77
|
+
#
|
|
78
|
+
# foo = Foo[1]
|
|
79
|
+
# foo.aasm.current_state # => :opened
|
|
80
|
+
# foo.close!
|
|
81
|
+
# foo.aasm.current_state # => :closed
|
|
82
|
+
# Foo[1].aasm.current_state # => :closed
|
|
83
|
+
#
|
|
84
|
+
# NOTE: intended to be called from an event
|
|
85
|
+
def aasm_write_state state
|
|
86
|
+
aasm_column = self.class.aasm_column
|
|
87
|
+
update_ony({aasm_column => state.to_s}, aasm_column)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
|
91
|
+
#
|
|
92
|
+
# foo = Foo[1]
|
|
93
|
+
# foo.aasm.current_state # => :opened
|
|
94
|
+
# foo.close
|
|
95
|
+
# foo.aasm.current_state # => :closed
|
|
96
|
+
# Foo[1].aasm.current_state # => :opened
|
|
97
|
+
# foo.save
|
|
98
|
+
# foo.aasm.current_state # => :closed
|
|
99
|
+
# Foo[1].aasm.current_state # => :closed
|
|
100
|
+
#
|
|
101
|
+
# NOTE: intended to be called from an event
|
|
102
|
+
def aasm_write_state_without_persistence state
|
|
103
|
+
send("#{self.class.aasm_column}=", state.to_s)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
data/lib/aasm/persistence.rb
CHANGED
|
@@ -12,6 +12,9 @@ module AASM
|
|
|
12
12
|
elsif hierarchy.include?("Mongoid::Document")
|
|
13
13
|
require_files_for(:mongoid)
|
|
14
14
|
base.send(:include, AASM::Persistence::MongoidPersistence)
|
|
15
|
+
elsif hierarchy.include?("Sequel::Model")
|
|
16
|
+
require_files_for(:sequel)
|
|
17
|
+
base.send(:include, AASM::Persistence::SequelPersistence)
|
|
15
18
|
end
|
|
16
19
|
end
|
|
17
20
|
|
data/lib/aasm/state.rb
CHANGED
|
@@ -2,9 +2,9 @@ module AASM
|
|
|
2
2
|
class State
|
|
3
3
|
attr_reader :name, :options
|
|
4
4
|
|
|
5
|
-
def initialize(name,
|
|
5
|
+
def initialize(name, klass, options={})
|
|
6
6
|
@name = name
|
|
7
|
-
@
|
|
7
|
+
@klass = klass
|
|
8
8
|
update(options)
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -48,7 +48,7 @@ module AASM
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def localized_name
|
|
51
|
-
AASM::Localizer.new.human_state_name(@
|
|
51
|
+
AASM::Localizer.new.human_state_name(@klass, self)
|
|
52
52
|
end
|
|
53
53
|
alias human_name localized_name
|
|
54
54
|
|
data/lib/aasm/state_machine.rb
CHANGED
|
@@ -2,20 +2,17 @@ module AASM
|
|
|
2
2
|
class StateMachine
|
|
3
3
|
|
|
4
4
|
# the following two methods provide the storage of all state machines
|
|
5
|
-
def self.[](
|
|
6
|
-
(@machines ||= {})[
|
|
5
|
+
def self.[](klass)
|
|
6
|
+
(@machines ||= {})[klass.to_s]
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def self.[]=(
|
|
10
|
-
(@machines ||= {})[
|
|
9
|
+
def self.[]=(klass, machine)
|
|
10
|
+
(@machines ||= {})[klass.to_s] = machine
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
attr_accessor :states, :events, :initial_state, :config
|
|
14
|
-
attr_reader :name
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
def initialize(name)
|
|
18
|
-
@name = name
|
|
15
|
+
def initialize
|
|
19
16
|
@initial_state = nil
|
|
20
17
|
@states = []
|
|
21
18
|
@events = {}
|
|
@@ -29,8 +26,15 @@ module AASM
|
|
|
29
26
|
@events = @events.dup
|
|
30
27
|
end
|
|
31
28
|
|
|
32
|
-
def add_state(name,
|
|
33
|
-
|
|
29
|
+
def add_state(name, klass, options)
|
|
30
|
+
set_initial_state(name, options)
|
|
31
|
+
@states << AASM::State.new(name, klass, options) unless @states.include?(name)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def set_initial_state(name, options)
|
|
37
|
+
@initial_state = name if options[:initial] || !initial_state
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
end # StateMachine
|
data/lib/aasm/version.rb
CHANGED
|
@@ -72,4 +72,13 @@ describe 'when being unsuspended' do
|
|
|
72
72
|
|
|
73
73
|
expect(auth.aasm.current_state).to eq(:passive)
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
it "should be able to fire known events" do
|
|
77
|
+
expect(auth.aasm.may_fire_event?(:activate)).to be_true
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should not be able to fire unknown events" do
|
|
81
|
+
expect(auth.aasm.may_fire_event?(:unknown)).to be_false
|
|
82
|
+
end
|
|
83
|
+
|
|
75
84
|
end
|
data/spec/unit/event_spec.rb
CHANGED
|
@@ -58,6 +58,23 @@ describe 'transition inspection' do
|
|
|
58
58
|
end
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
+
describe 'transition inspection without from' do
|
|
62
|
+
let(:event) do
|
|
63
|
+
AASM::Event.new(:run) do
|
|
64
|
+
transitions :to => :running
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it 'should support inspecting transitions from other states' do
|
|
69
|
+
expect(event.transitions_from_state(:sleeping).map(&:to)).to eq([:running])
|
|
70
|
+
expect(event.transitions_from_state?(:sleeping)).to be_true
|
|
71
|
+
|
|
72
|
+
expect(event.transitions_from_state(:cleaning).map(&:to)).to eq([:running])
|
|
73
|
+
expect(event.transitions_from_state?(:cleaning)).to be_true
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
61
78
|
describe 'firing an event' do
|
|
62
79
|
it 'should return nil if the transitions are empty' do
|
|
63
80
|
obj = double('object', :aasm => double('aasm', :current_state => 'open'))
|
|
@@ -147,6 +147,6 @@ describe 'mongoid', :if => Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version
|
|
|
147
147
|
end
|
|
148
148
|
|
|
149
149
|
rescue LoadError
|
|
150
|
-
puts "Not running Mongoid specs because mongoid gem
|
|
150
|
+
puts "Not running Mongoid specs because mongoid gem is not installed!!!"
|
|
151
151
|
end
|
|
152
152
|
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
describe 'sequel' do
|
|
3
|
+
begin
|
|
4
|
+
require 'sequel'
|
|
5
|
+
require 'logger'
|
|
6
|
+
require 'spec_helper'
|
|
7
|
+
|
|
8
|
+
before(:all) do
|
|
9
|
+
db = Sequel.sqlite
|
|
10
|
+
# if you want to see the statements while running the spec enable the following line
|
|
11
|
+
# db.loggers << Logger.new($stderr)
|
|
12
|
+
db.create_table(:models) do
|
|
13
|
+
primary_key :id
|
|
14
|
+
String :status
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@model = Class.new(Sequel::Model(db)) do
|
|
18
|
+
set_dataset(:models)
|
|
19
|
+
attr_accessor :default
|
|
20
|
+
include AASM
|
|
21
|
+
aasm :column => :status
|
|
22
|
+
aasm do
|
|
23
|
+
state :alpha, :initial => true
|
|
24
|
+
state :beta
|
|
25
|
+
state :gamma
|
|
26
|
+
event :release do
|
|
27
|
+
transitions :from => [:alpha, :beta, :gamma], :to => :beta
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "instance methods" do
|
|
34
|
+
let(:model) {@model.new}
|
|
35
|
+
|
|
36
|
+
it "should respond to aasm persistence methods" do
|
|
37
|
+
expect(model).to respond_to(:aasm_read_state)
|
|
38
|
+
expect(model).to respond_to(:aasm_write_state)
|
|
39
|
+
expect(model).to respond_to(:aasm_write_state_without_persistence)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should return the initial state when new and the aasm field is nil" do
|
|
43
|
+
expect(model.aasm.current_state).to eq(:alpha)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should return the aasm column when new and the aasm field is not nil" do
|
|
47
|
+
model.status = "beta"
|
|
48
|
+
expect(model.aasm.current_state).to eq(:beta)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should return the aasm column when not new and the aasm_column is not nil" do
|
|
52
|
+
allow(model).to receive(:new?).and_return(false)
|
|
53
|
+
model.status = "gamma"
|
|
54
|
+
expect(model.aasm.current_state).to eq(:gamma)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should allow a nil state" do
|
|
58
|
+
allow(model).to receive(:new?).and_return(false)
|
|
59
|
+
model.status = nil
|
|
60
|
+
expect(model.aasm.current_state).to be_nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should call aasm_ensure_initial_state on validation before create" do
|
|
64
|
+
expect(model).to receive(:aasm_ensure_initial_state).and_return(true)
|
|
65
|
+
model.valid?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should call aasm_ensure_initial_state before create, even if skipping validations" do
|
|
69
|
+
expect(model).to receive(:aasm_ensure_initial_state).and_return(true)
|
|
70
|
+
model.save(:validate => false)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe 'subclasses' do
|
|
75
|
+
it "should have the same states as its parent class" do
|
|
76
|
+
expect(Class.new(@model).aasm.states).to eq(@model.aasm.states)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "should have the same events as its parent class" do
|
|
80
|
+
expect(Class.new(@model).aasm.events).to eq(@model.aasm.events)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "should have the same column as its parent even for the new dsl" do
|
|
84
|
+
expect(@model.aasm_column).to eq(:status)
|
|
85
|
+
expect(Class.new(@model).aasm_column).to eq(:status)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe 'initial states' do
|
|
90
|
+
it 'should support conditions' do
|
|
91
|
+
@model.aasm do
|
|
92
|
+
initial_state lambda{ |m| m.default }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
expect(@model.new(:default => :beta).aasm.current_state).to eq(:beta)
|
|
96
|
+
expect(@model.new(:default => :gamma).aasm.current_state).to eq(:gamma)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
rescue LoadError
|
|
101
|
+
puts "Not running Sequel specs because sequel gem is not installed!!!"
|
|
102
|
+
end
|
|
103
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aasm
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.1
|
|
4
|
+
version: 3.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Barron
|
|
@@ -11,7 +11,7 @@ authors:
|
|
|
11
11
|
autorequire:
|
|
12
12
|
bindir: bin
|
|
13
13
|
cert_chain: []
|
|
14
|
-
date: 2014-
|
|
14
|
+
date: 2014-06-14 00:00:00.000000000 Z
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
17
17
|
name: rake
|
|
@@ -45,14 +45,14 @@ dependencies:
|
|
|
45
45
|
name: rspec
|
|
46
46
|
requirement: !ruby/object:Gem::Requirement
|
|
47
47
|
requirements:
|
|
48
|
-
- - "
|
|
48
|
+
- - "~>"
|
|
49
49
|
- !ruby/object:Gem::Version
|
|
50
50
|
version: '2.14'
|
|
51
51
|
type: :development
|
|
52
52
|
prerelease: false
|
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
|
54
54
|
requirements:
|
|
55
|
-
- - "
|
|
55
|
+
- - "~>"
|
|
56
56
|
- !ruby/object:Gem::Version
|
|
57
57
|
version: '2.14'
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
@@ -129,6 +129,7 @@ files:
|
|
|
129
129
|
- lib/aasm/persistence/active_record_persistence.rb
|
|
130
130
|
- lib/aasm/persistence/base.rb
|
|
131
131
|
- lib/aasm/persistence/mongoid_persistence.rb
|
|
132
|
+
- lib/aasm/persistence/sequel_persistence.rb
|
|
132
133
|
- lib/aasm/state.rb
|
|
133
134
|
- lib/aasm/state_machine.rb
|
|
134
135
|
- lib/aasm/transition.rb
|
|
@@ -174,6 +175,7 @@ files:
|
|
|
174
175
|
- spec/unit/new_dsl_spec.rb
|
|
175
176
|
- spec/unit/persistence/active_record_persistence_spec.rb
|
|
176
177
|
- spec/unit/persistence/mongoid_persistance_spec.rb
|
|
178
|
+
- spec/unit/persistence/sequel_persistence_spec.rb
|
|
177
179
|
- spec/unit/simple_example_spec.rb
|
|
178
180
|
- spec/unit/state_spec.rb
|
|
179
181
|
- spec/unit/subclassing_spec.rb
|
|
@@ -198,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
198
200
|
version: '0'
|
|
199
201
|
requirements: []
|
|
200
202
|
rubyforge_project:
|
|
201
|
-
rubygems_version: 2.
|
|
203
|
+
rubygems_version: 2.2.2
|
|
202
204
|
signing_key:
|
|
203
205
|
specification_version: 4
|
|
204
206
|
summary: State machine mixin for Ruby objects
|
|
@@ -244,6 +246,7 @@ test_files:
|
|
|
244
246
|
- spec/unit/new_dsl_spec.rb
|
|
245
247
|
- spec/unit/persistence/active_record_persistence_spec.rb
|
|
246
248
|
- spec/unit/persistence/mongoid_persistance_spec.rb
|
|
249
|
+
- spec/unit/persistence/sequel_persistence_spec.rb
|
|
247
250
|
- spec/unit/simple_example_spec.rb
|
|
248
251
|
- spec/unit/state_spec.rb
|
|
249
252
|
- spec/unit/subclassing_spec.rb
|