aasm 4.9.0 → 4.10.0
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/.travis.yml +9 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile +3 -0
- data/README.md +27 -11
- data/gemfiles/rails_4.0.gemfile +1 -0
- data/gemfiles/rails_4.1.gemfile +1 -0
- data/gemfiles/rails_4.2_mongo_mapper.gemfile +1 -0
- data/lib/aasm.rb +3 -1
- data/lib/aasm/aasm.rb +13 -9
- data/lib/aasm/base.rb +67 -28
- data/lib/aasm/configuration.rb +3 -0
- data/lib/aasm/core/event.rb +8 -1
- data/lib/aasm/core/transition.rb +32 -4
- data/lib/aasm/errors.rb +4 -4
- data/lib/aasm/persistence.rb +14 -1
- data/lib/aasm/persistence/active_record_persistence.rb +27 -13
- data/lib/aasm/persistence/base.rb +2 -44
- data/lib/aasm/persistence/core_data_query_persistence.rb +93 -0
- data/lib/aasm/persistence/dynamoid_persistence.rb +2 -4
- data/lib/aasm/persistence/mongo_mapper_persistence.rb +15 -9
- data/lib/aasm/persistence/mongoid_persistence.rb +24 -4
- data/lib/aasm/persistence/redis_persistence.rb +107 -0
- data/lib/aasm/persistence/sequel_persistence.rb +1 -3
- data/lib/aasm/state_machine.rb +1 -9
- data/lib/aasm/state_machine_store.rb +73 -0
- data/lib/aasm/version.rb +1 -1
- data/lib/generators/active_record/templates/migration_existing.rb +2 -6
- data/lib/motion-aasm.rb +35 -0
- data/spec/models/callbacks/basic.rb +12 -2
- data/spec/models/callbacks/guard_within_block.rb +2 -1
- data/spec/models/callbacks/multiple_transitions_transition_guard.rb +2 -1
- data/spec/models/callbacks/with_args.rb +2 -1
- data/spec/models/callbacks/with_state_arg.rb +6 -2
- data/spec/models/mongoid/mongoid_relationships.rb +26 -0
- data/spec/models/namespaced_multiple_example.rb +28 -0
- data/spec/models/parametrised_event.rb +9 -3
- data/spec/models/states_on_one_line_example.rb +8 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/api_spec.rb +20 -0
- data/spec/unit/callbacks_spec.rb +17 -5
- data/spec/unit/event_spec.rb +19 -1
- data/spec/unit/exception_spec.rb +11 -0
- data/spec/unit/memory_leak_spec.rb +1 -1
- data/spec/unit/namespaced_multiple_example_spec.rb +53 -0
- data/spec/unit/override_warning_spec.rb +43 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +1 -1
- data/spec/unit/persistence/active_record_persistence_spec.rb +1 -1
- data/spec/unit/persistence/mongoid_persistence_spec.rb +11 -0
- data/spec/unit/persistence/redis_persistence_spec.rb +77 -0
- data/spec/unit/readme_spec.rb +1 -2
- data/spec/unit/states_on_one_line_example_spec.rb +16 -0
- data/spec/unit/transition_spec.rb +60 -1
- metadata +22 -2
data/lib/aasm/core/event.rb
CHANGED
@@ -8,6 +8,7 @@ module AASM::Core
|
|
8
8
|
@name = name
|
9
9
|
@state_machine = state_machine
|
10
10
|
@transitions = []
|
11
|
+
@valid_transitions = {}
|
11
12
|
@guards = Array(options[:guard] || options[:guards] || options[:if])
|
12
13
|
@unless = Array(options[:unless]) #TODO: This could use a better name
|
13
14
|
|
@@ -62,6 +63,12 @@ module AASM::Core
|
|
62
63
|
invoke_callbacks(@options[callback_name], record, args)
|
63
64
|
end
|
64
65
|
|
66
|
+
def fire_transition_callbacks(obj, *args)
|
67
|
+
from_state = obj.aasm(state_machine.name).current_state
|
68
|
+
transition = @valid_transitions[from_state]
|
69
|
+
@valid_transitions[from_state].invoke_success_callbacks(obj, *args) if transition
|
70
|
+
end
|
71
|
+
|
65
72
|
def ==(event)
|
66
73
|
if event.is_a? Symbol
|
67
74
|
name == event
|
@@ -103,7 +110,6 @@ module AASM::Core
|
|
103
110
|
definitions
|
104
111
|
end
|
105
112
|
|
106
|
-
# Execute if test == false, otherwise return true/false depending on whether it would fire
|
107
113
|
def _fire(obj, options={}, to_state=nil, *args)
|
108
114
|
result = options[:test_only] ? false : nil
|
109
115
|
if @transitions.map(&:from).any?
|
@@ -130,6 +136,7 @@ module AASM::Core
|
|
130
136
|
if options[:test_only]
|
131
137
|
# result = true
|
132
138
|
else
|
139
|
+
Array(transition.to).each {|to| @valid_transitions[to] = transition }
|
133
140
|
transition.execute(obj, *args)
|
134
141
|
end
|
135
142
|
|
data/lib/aasm/core/transition.rb
CHANGED
@@ -6,7 +6,7 @@ module AASM::Core
|
|
6
6
|
alias_method :options, :opts
|
7
7
|
|
8
8
|
def initialize(event, opts, &block)
|
9
|
-
add_options_from_dsl(opts, [:on_transition, :guard, :after], &block) if block
|
9
|
+
add_options_from_dsl(opts, [:on_transition, :guard, :after, :success], &block) if block
|
10
10
|
|
11
11
|
@event = event
|
12
12
|
@from = opts[:from]
|
@@ -22,6 +22,9 @@ module AASM::Core
|
|
22
22
|
@after = Array(opts[:after])
|
23
23
|
@after = @after[0] if @after.size == 1
|
24
24
|
|
25
|
+
@success = Array(opts[:success])
|
26
|
+
@success = @success[0] if @success.size == 1
|
27
|
+
|
25
28
|
@opts = opts
|
26
29
|
end
|
27
30
|
|
@@ -43,6 +46,10 @@ module AASM::Core
|
|
43
46
|
@from == value
|
44
47
|
end
|
45
48
|
|
49
|
+
def invoke_success_callbacks(obj, *args)
|
50
|
+
_fire_callbacks(@success, obj, args)
|
51
|
+
end
|
52
|
+
|
46
53
|
private
|
47
54
|
|
48
55
|
def invoke_callbacks_compatible_with_guard(code, record, args, options={})
|
@@ -53,13 +60,13 @@ module AASM::Core
|
|
53
60
|
|
54
61
|
case code
|
55
62
|
when Symbol, String
|
56
|
-
result = (record.__send__(:method, code.to_sym).arity == 0 ? record.__send__(code) :
|
63
|
+
result = (record.__send__(:method, code.to_sym).arity == 0 ? record.__send__(code) : record.__send__(code, *args))
|
57
64
|
failures << code unless result
|
58
65
|
result
|
59
66
|
when Proc
|
60
67
|
if code.respond_to?(:parameters)
|
61
68
|
# In Ruby's Proc, the 'arity' method is not a good condidate to know if
|
62
|
-
# we should pass the arguments or not, since
|
69
|
+
# we should pass the arguments or not, since it does return 0 even in
|
63
70
|
# presence of optional parameters.
|
64
71
|
result = (code.parameters.size == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code))
|
65
72
|
|
@@ -85,7 +92,14 @@ module AASM::Core
|
|
85
92
|
instance = code.new(record, *args)
|
86
93
|
end
|
87
94
|
result = instance.call
|
88
|
-
|
95
|
+
|
96
|
+
if Method.method_defined?(:source_location)
|
97
|
+
failures << instance.method(:call).source_location.join('#') unless result
|
98
|
+
else
|
99
|
+
# RubyMotion support ('source_location' not defined for Method)
|
100
|
+
failures << instance.method(:call) unless result
|
101
|
+
end
|
102
|
+
|
89
103
|
result
|
90
104
|
when Array
|
91
105
|
if options[:guard]
|
@@ -103,5 +117,19 @@ module AASM::Core
|
|
103
117
|
end
|
104
118
|
end
|
105
119
|
|
120
|
+
def _fire_callbacks(code, record, args)
|
121
|
+
case code
|
122
|
+
when Symbol, String
|
123
|
+
arity = record.send(:method, code.to_sym).arity
|
124
|
+
record.send(code, *(arity < 0 ? args : args[0...arity]))
|
125
|
+
when Proc
|
126
|
+
code.arity == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code)
|
127
|
+
when Array
|
128
|
+
@success.map {|a| _fire_callbacks(a, obj, args)}
|
129
|
+
else
|
130
|
+
true
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
106
134
|
end
|
107
135
|
end # AASM
|
data/lib/aasm/errors.rb
CHANGED
@@ -3,18 +3,18 @@ module AASM
|
|
3
3
|
class UnknownStateMachineError < RuntimeError; end
|
4
4
|
|
5
5
|
class InvalidTransition < RuntimeError
|
6
|
-
attr_reader :object, :event_name, :
|
6
|
+
attr_reader :object, :event_name, :originating_state, :failures
|
7
7
|
|
8
8
|
def initialize(object, event_name, state_machine_name, failures = [])
|
9
|
-
@object, @event_name, @
|
9
|
+
@object, @event_name, @originating_state, @failures = object, event_name, object.aasm(state_machine_name).current_state, failures
|
10
10
|
end
|
11
11
|
|
12
12
|
def message
|
13
|
-
"Event '#{event_name}' cannot transition from '#{
|
13
|
+
"Event '#{event_name}' cannot transition from '#{originating_state}'. #{reasoning}"
|
14
14
|
end
|
15
15
|
|
16
16
|
def reasoning
|
17
|
-
"Failed callback(s): #{
|
17
|
+
"Failed callback(s): #{failures}." unless failures.empty?
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
data/lib/aasm/persistence.rb
CHANGED
@@ -7,15 +7,25 @@ module AASM
|
|
7
7
|
hierarchy = base.ancestors.map {|klass| klass.to_s}
|
8
8
|
|
9
9
|
if hierarchy.include?("ActiveRecord::Base")
|
10
|
+
require_persistence :active_record
|
10
11
|
include_persistence base, :active_record
|
11
12
|
elsif hierarchy.include?("Mongoid::Document")
|
13
|
+
require_persistence :mongoid
|
12
14
|
include_persistence base, :mongoid
|
13
15
|
elsif hierarchy.include?("MongoMapper::Document")
|
16
|
+
require_persistence :mongo_mapper
|
14
17
|
include_persistence base, :mongo_mapper
|
15
18
|
elsif hierarchy.include?("Sequel::Model")
|
19
|
+
require_persistence :sequel
|
16
20
|
include_persistence base, :sequel
|
17
21
|
elsif hierarchy.include?("Dynamoid::Document")
|
22
|
+
require_persistence :dynamoid
|
18
23
|
include_persistence base, :dynamoid
|
24
|
+
elsif hierarchy.include?("Redis::Objects")
|
25
|
+
require_persistence :redis
|
26
|
+
include_persistence base, :redis
|
27
|
+
elsif hierarchy.include?("CDQManagedObject")
|
28
|
+
include_persistence base, :core_data_query
|
19
29
|
else
|
20
30
|
include_persistence base, :plain
|
21
31
|
end
|
@@ -23,8 +33,11 @@ module AASM
|
|
23
33
|
|
24
34
|
private
|
25
35
|
|
26
|
-
def
|
36
|
+
def require_persistence(type)
|
27
37
|
require File.join(File.dirname(__FILE__), 'persistence', "#{type}_persistence")
|
38
|
+
end
|
39
|
+
|
40
|
+
def include_persistence(base, type)
|
28
41
|
base.send(:include, constantize("#{capitalize(type)}Persistence"))
|
29
42
|
end
|
30
43
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'base'
|
2
|
-
|
3
1
|
module AASM
|
4
2
|
module Persistence
|
5
3
|
module ActiveRecordPersistence
|
@@ -31,15 +29,31 @@ module AASM
|
|
31
29
|
def self.included(base)
|
32
30
|
base.send(:include, AASM::Persistence::Base)
|
33
31
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
32
|
+
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
34
33
|
|
35
|
-
base.after_initialize
|
36
|
-
aasm_ensure_initial_state
|
37
|
-
end
|
34
|
+
base.after_initialize :aasm_ensure_initial_state
|
38
35
|
|
39
36
|
# ensure state is in the list of states
|
40
37
|
base.validate :aasm_validate_states
|
41
38
|
end
|
42
39
|
|
40
|
+
module ClassMethods
|
41
|
+
def aasm_create_scope(state_machine_name, scope_name)
|
42
|
+
conditions = {
|
43
|
+
table_name => { aasm(state_machine_name).attribute_name => scope_name.to_s }
|
44
|
+
}
|
45
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
46
|
+
class_eval do
|
47
|
+
scope scope_name, lambda { where(conditions) }
|
48
|
+
end
|
49
|
+
else
|
50
|
+
class_eval do
|
51
|
+
named_scope scope_name, :conditions => conditions
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
43
57
|
module InstanceMethods
|
44
58
|
|
45
59
|
# Writes <tt>state</tt> to the state column and persists it to the database
|
@@ -93,11 +107,11 @@ module AASM
|
|
93
107
|
end
|
94
108
|
|
95
109
|
def aasm_enum(name=:default)
|
96
|
-
case AASM::
|
110
|
+
case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
97
111
|
when false then nil
|
98
112
|
when true then aasm_guess_enum_method(name)
|
99
113
|
when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
|
100
|
-
else AASM::
|
114
|
+
else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
101
115
|
end
|
102
116
|
end
|
103
117
|
|
@@ -113,7 +127,7 @@ module AASM
|
|
113
127
|
end
|
114
128
|
|
115
129
|
def aasm_skipping_validations(state_machine_name)
|
116
|
-
AASM::
|
130
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
117
131
|
end
|
118
132
|
|
119
133
|
def aasm_write_attribute(state, name=:default)
|
@@ -142,7 +156,7 @@ module AASM
|
|
142
156
|
# foo.aasm_state # => nil
|
143
157
|
#
|
144
158
|
def aasm_ensure_initial_state
|
145
|
-
AASM::
|
159
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
146
160
|
# checking via respond_to? does not work in Rails <= 3
|
147
161
|
# if respond_to?(self.class.aasm(state_machine_name).attribute_name) && send(self.class.aasm(state_machine_name).attribute_name).blank? # Rails 4
|
148
162
|
if aasm_column_is_blank?(state_machine_name)
|
@@ -189,18 +203,18 @@ module AASM
|
|
189
203
|
end
|
190
204
|
|
191
205
|
def requires_new?(state_machine_name)
|
192
|
-
AASM::
|
206
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_new_transaction
|
193
207
|
end
|
194
208
|
|
195
209
|
def requires_lock?(state_machine_name)
|
196
|
-
AASM::
|
210
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_lock
|
197
211
|
end
|
198
212
|
|
199
213
|
def aasm_validate_states
|
200
|
-
AASM::
|
214
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
201
215
|
unless aasm_skipping_validations(state_machine_name)
|
202
216
|
if aasm_invalid_state?(state_machine_name)
|
203
|
-
self.errors.add(AASM::
|
217
|
+
self.errors.add(AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.column , "is invalid")
|
204
218
|
end
|
205
219
|
end
|
206
220
|
end
|
@@ -63,53 +63,11 @@ module AASM
|
|
63
63
|
private
|
64
64
|
|
65
65
|
def create_scope?(name)
|
66
|
-
@state_machine.config.create_scopes && !@klass.respond_to?(name)
|
66
|
+
@state_machine.config.create_scopes && !@klass.respond_to?(name) && @klass.respond_to?(:aasm_create_scope)
|
67
67
|
end
|
68
68
|
|
69
69
|
def create_scope(name)
|
70
|
-
|
71
|
-
create_for_active_record(name)
|
72
|
-
elsif ancestors_include?("Mongoid::Document")
|
73
|
-
create_for_mongoid(name)
|
74
|
-
elsif ancestors_include?("MongoMapper::Document")
|
75
|
-
create_for_mongomapper(name)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def ancestors_include?(class_name)
|
80
|
-
@klass.ancestors.map { |klass| klass.to_s }.include?(class_name)
|
81
|
-
end
|
82
|
-
|
83
|
-
def create_for_active_record(name)
|
84
|
-
conditions = {
|
85
|
-
@klass.table_name => { @klass.aasm(@name).attribute_name => name.to_s }
|
86
|
-
}
|
87
|
-
if ActiveRecord::VERSION::MAJOR >= 3
|
88
|
-
@klass.class_eval do
|
89
|
-
scope name, lambda { where(conditions) }
|
90
|
-
end
|
91
|
-
else
|
92
|
-
@klass.class_eval do
|
93
|
-
named_scope name, :conditions => conditions
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def create_for_mongoid(name)
|
99
|
-
klass = @klass
|
100
|
-
state_machine_name = @name
|
101
|
-
scope_options = lambda {
|
102
|
-
klass.send(
|
103
|
-
:where,
|
104
|
-
{ klass.aasm(state_machine_name).attribute_name.to_sym => name.to_s }
|
105
|
-
)
|
106
|
-
}
|
107
|
-
@klass.send(:scope, name, scope_options)
|
108
|
-
end
|
109
|
-
|
110
|
-
def create_for_mongomapper(name)
|
111
|
-
conditions = { @klass.aasm(@name).attribute_name.to_sym => name.to_s }
|
112
|
-
@klass.scope(name, lambda { @klass.where(conditions) })
|
70
|
+
@klass.aasm_create_scope(@name, name)
|
113
71
|
end
|
114
72
|
end # Base
|
115
73
|
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module AASM
|
2
|
+
module Persistence
|
3
|
+
module CoreDataQueryPersistence
|
4
|
+
# This method:
|
5
|
+
#
|
6
|
+
# * extends the model with ClassMethods
|
7
|
+
# * includes InstanceMethods
|
8
|
+
#
|
9
|
+
# Adds
|
10
|
+
#
|
11
|
+
# after_initialize :aasm_ensure_initial_state
|
12
|
+
#
|
13
|
+
|
14
|
+
def self.included(base)
|
15
|
+
base.send(:include, AASM::Persistence::Base)
|
16
|
+
base.send(:include, AASM::Persistence::CoreDataQueryPersistence::InstanceMethods)
|
17
|
+
base.extend AASM::Persistence::CoreDataQueryPersistence::ClassMethods
|
18
|
+
|
19
|
+
base.after_initialize :aasm_ensure_initial_state
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def aasm_create_scope(state_machine_name, scope_name)
|
24
|
+
scope(scope_name.to_sym, lambda { where(aasm(state_machine_name).attribute_name.to_sym).eq(scope_name.to_s) })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module InstanceMethods
|
29
|
+
|
30
|
+
# Writes <tt>state</tt> to the state column and persists it to the database
|
31
|
+
# using update_attribute (which bypasses validation)
|
32
|
+
#
|
33
|
+
# foo = Foo.find(1)
|
34
|
+
# foo.aasm.current_state # => :opened
|
35
|
+
# foo.close!
|
36
|
+
# foo.aasm.current_state # => :closed
|
37
|
+
# Foo.find(1).aasm.current_state # => :closed
|
38
|
+
#
|
39
|
+
# NOTE: intended to be called from an event
|
40
|
+
def aasm_write_state(state, name=:default)
|
41
|
+
raise "Cowardly refusing to save the current CoreDataQuery context"
|
42
|
+
aasm_write_state_without_persistence(state, name)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
46
|
+
#
|
47
|
+
# foo = Foo.find(1)
|
48
|
+
# foo.aasm.current_state # => :opened
|
49
|
+
# foo.close
|
50
|
+
# foo.aasm.current_state # => :closed
|
51
|
+
# Foo.find(1).aasm.current_state # => :opened
|
52
|
+
# foo.save
|
53
|
+
# foo.aasm.current_state # => :closed
|
54
|
+
# Foo.find(1).aasm.current_state # => :closed
|
55
|
+
#
|
56
|
+
# NOTE: intended to be called from an event
|
57
|
+
def aasm_write_state_without_persistence(state, name=:default)
|
58
|
+
write_attribute(self.class.aasm(name).attribute_name, state.to_s)
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Ensures that if the aasm_state column is nil and the record is new
|
64
|
+
# that the initial state gets populated before validation on create
|
65
|
+
#
|
66
|
+
# foo = Foo.new
|
67
|
+
# foo.aasm_state # => nil
|
68
|
+
# foo.valid?
|
69
|
+
# foo.aasm_state # => "open" (where :open is the initial state)
|
70
|
+
#
|
71
|
+
#
|
72
|
+
# foo = Foo.find(:first)
|
73
|
+
# foo.aasm_state # => 1
|
74
|
+
# foo.aasm_state = nil
|
75
|
+
# foo.valid?
|
76
|
+
# foo.aasm_state # => nil
|
77
|
+
#
|
78
|
+
def aasm_ensure_initial_state
|
79
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
80
|
+
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end # InstanceMethods
|
84
|
+
|
85
|
+
# module NamedScopeMethods
|
86
|
+
# def aasm_state_with_named_scope name, options = {}
|
87
|
+
# aasm_state_without_named_scope name, options
|
88
|
+
# self.named_scope name, :conditions => { "#{table_name}.#{self.aasm.attribute_name}" => name.to_s} unless self.respond_to?(name)
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
end
|
92
|
+
end # Persistence
|
93
|
+
end # AASM
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'base'
|
2
|
-
|
3
1
|
module AASM
|
4
2
|
module Persistence
|
5
3
|
module DynamoidPersistence
|
@@ -16,7 +14,7 @@ module AASM
|
|
16
14
|
#
|
17
15
|
base.class_eval %Q(
|
18
16
|
def method_missing(method_name, *arguments, &block)
|
19
|
-
if (AASM::
|
17
|
+
if (AASM::StateMachineStore.fetch(self.class, true).machine_names.map { |state_machine_name| self.class.aasm(state_machine_name).attribute_name.to_s + "=" }).include? method_name.to_s
|
20
18
|
attribute_name = method_name.to_s.gsub("=", '')
|
21
19
|
write_attribute(attribute_name.to_sym, *arguments)
|
22
20
|
else
|
@@ -84,7 +82,7 @@ module AASM
|
|
84
82
|
# foo.aasm_state # => nil
|
85
83
|
#
|
86
84
|
def aasm_ensure_initial_state
|
87
|
-
AASM::
|
85
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
88
86
|
aasm(state_machine_name).enter_initial_state if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
89
87
|
end
|
90
88
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'base'
|
2
|
-
|
3
1
|
module AASM
|
4
2
|
module Persistence
|
5
3
|
module MongoMapperPersistence
|
@@ -33,6 +31,7 @@ module AASM
|
|
33
31
|
def self.included(base)
|
34
32
|
base.send(:include, AASM::Persistence::Base)
|
35
33
|
base.send(:include, AASM::Persistence::MongoMapperPersistence::InstanceMethods)
|
34
|
+
base.extend AASM::Persistence::MongoMapperPersistence::ClassMethods
|
36
35
|
|
37
36
|
base.before_create :aasm_ensure_initial_state
|
38
37
|
|
@@ -40,6 +39,13 @@ module AASM
|
|
40
39
|
base.validate :aasm_validate_states
|
41
40
|
end
|
42
41
|
|
42
|
+
module ClassMethods
|
43
|
+
def aasm_create_scope(state_machine_name, scope_name)
|
44
|
+
conditions = { aasm(state_machine_name).attribute_name.to_sym => scope_name.to_s }
|
45
|
+
scope(scope_name, lambda { where(conditions) })
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
43
49
|
module InstanceMethods
|
44
50
|
|
45
51
|
# Writes <tt>state</tt> to the state column and persists it to the database
|
@@ -87,11 +93,11 @@ module AASM
|
|
87
93
|
|
88
94
|
private
|
89
95
|
def aasm_enum(name=:default)
|
90
|
-
case AASM::
|
96
|
+
case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
91
97
|
when false then nil
|
92
98
|
when true then aasm_guess_enum_method(name)
|
93
99
|
when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
|
94
|
-
else AASM::
|
100
|
+
else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
95
101
|
end
|
96
102
|
end
|
97
103
|
|
@@ -104,7 +110,7 @@ module AASM
|
|
104
110
|
end
|
105
111
|
|
106
112
|
def aasm_skipping_validations(state_machine_name)
|
107
|
-
AASM::
|
113
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
108
114
|
end
|
109
115
|
|
110
116
|
def aasm_write_attribute(state, name=:default)
|
@@ -135,17 +141,17 @@ module AASM
|
|
135
141
|
# foo.aasm_state # => nil
|
136
142
|
#
|
137
143
|
def aasm_ensure_initial_state
|
138
|
-
AASM::
|
144
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
139
145
|
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
140
146
|
end
|
141
147
|
end
|
142
148
|
|
143
149
|
def aasm_validate_states
|
144
|
-
AASM::
|
150
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
145
151
|
send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s) if send(self.class.aasm(state_machine_name).attribute_name).blank?
|
146
|
-
unless AASM::
|
152
|
+
unless AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
147
153
|
if aasm(state_machine_name).current_state && !aasm(state_machine_name).states.include?(aasm(state_machine_name).current_state)
|
148
|
-
self.errors.add(AASM::
|
154
|
+
self.errors.add(AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.column , "is invalid")
|
149
155
|
end
|
150
156
|
end
|
151
157
|
end
|