aasm 4.11.1 → 4.12.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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +19 -16
  3. data/Appraisals +46 -0
  4. data/CHANGELOG.md +19 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +4 -21
  7. data/README.md +154 -39
  8. data/Rakefile +6 -1
  9. data/TESTING.md +25 -0
  10. data/aasm.gemspec +3 -0
  11. data/gemfiles/rails_3.2.gemfile +13 -0
  12. data/gemfiles/rails_4.0.gemfile +8 -9
  13. data/gemfiles/rails_4.2.gemfile +10 -9
  14. data/gemfiles/rails_4.2_mongoid_5.gemfile +5 -9
  15. data/gemfiles/rails_5.0.gemfile +8 -16
  16. data/lib/aasm/aasm.rb +9 -3
  17. data/lib/aasm/base.rb +11 -1
  18. data/lib/aasm/configuration.rb +4 -0
  19. data/lib/aasm/core/event.rb +18 -4
  20. data/lib/aasm/core/state.rb +7 -0
  21. data/lib/aasm/core/transition.rb +10 -1
  22. data/lib/aasm/instance_base.rb +0 -2
  23. data/lib/aasm/minitest/allow_event.rb +13 -0
  24. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  25. data/lib/aasm/minitest/have_state.rb +13 -0
  26. data/lib/aasm/minitest/transition_from.rb +21 -0
  27. data/lib/aasm/minitest.rb +5 -0
  28. data/lib/aasm/minitest_spec.rb +15 -0
  29. data/lib/aasm/persistence/active_record_persistence.rb +25 -101
  30. data/lib/aasm/persistence/base.rb +7 -3
  31. data/lib/aasm/persistence/mongoid_persistence.rb +25 -31
  32. data/lib/aasm/persistence/orm.rb +142 -0
  33. data/lib/aasm/persistence/redis_persistence.rb +16 -11
  34. data/lib/aasm/persistence/sequel_persistence.rb +36 -63
  35. data/lib/aasm/persistence.rb +0 -3
  36. data/lib/aasm/state_machine.rb +4 -2
  37. data/lib/aasm/state_machine_store.rb +5 -2
  38. data/lib/aasm/version.rb +1 -1
  39. data/lib/generators/active_record/templates/migration.rb +1 -1
  40. data/lib/generators/active_record/templates/migration_existing.rb +1 -1
  41. data/lib/motion-aasm.rb +2 -1
  42. data/spec/generators/active_record_generator_spec.rb +42 -39
  43. data/spec/generators/mongoid_generator_spec.rb +4 -6
  44. data/spec/models/active_record/complex_active_record_example.rb +5 -1
  45. data/spec/models/{invalid_persistor.rb → active_record/invalid_persistor.rb} +0 -2
  46. data/spec/models/{silent_persistor.rb → active_record/silent_persistor.rb} +0 -2
  47. data/spec/models/{transactor.rb → active_record/transactor.rb} +0 -2
  48. data/spec/models/{validator.rb → active_record/validator.rb} +0 -2
  49. data/spec/models/callbacks/basic.rb +5 -2
  50. data/spec/models/guard_with_params.rb +1 -1
  51. data/spec/models/guardian_without_from_specified.rb +18 -0
  52. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  53. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  54. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  55. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  56. data/spec/models/namespaced_multiple_example.rb +14 -0
  57. data/spec/models/parametrised_event.rb +7 -0
  58. data/spec/models/{mongo_mapper/complex_mongo_mapper_example.rb → redis/complex_redis_example.rb} +8 -5
  59. data/spec/models/redis/redis_multiple.rb +20 -0
  60. data/spec/models/redis/redis_simple.rb +20 -0
  61. data/spec/models/sequel/complex_sequel_example.rb +4 -3
  62. data/spec/models/sequel/invalid_persistor.rb +52 -0
  63. data/spec/models/sequel/sequel_multiple.rb +13 -13
  64. data/spec/models/sequel/sequel_simple.rb +13 -12
  65. data/spec/models/sequel/silent_persistor.rb +50 -0
  66. data/spec/models/sequel/transactor.rb +112 -0
  67. data/spec/models/sequel/validator.rb +93 -0
  68. data/spec/models/sequel/worker.rb +12 -0
  69. data/spec/models/simple_multiple_example.rb +12 -0
  70. data/spec/models/sub_class.rb +34 -0
  71. data/spec/spec_helper.rb +0 -33
  72. data/spec/spec_helpers/active_record.rb +7 -0
  73. data/spec/spec_helpers/dynamoid.rb +33 -0
  74. data/spec/spec_helpers/mongoid.rb +7 -0
  75. data/spec/spec_helpers/redis.rb +15 -0
  76. data/spec/spec_helpers/remove_warnings.rb +1 -0
  77. data/spec/spec_helpers/sequel.rb +7 -0
  78. data/spec/unit/api_spec.rb +76 -73
  79. data/spec/unit/callbacks_spec.rb +5 -0
  80. data/spec/unit/event_spec.rb +12 -0
  81. data/spec/unit/guard_spec.rb +17 -0
  82. data/spec/unit/guard_with_params_spec.rb +4 -0
  83. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  84. data/spec/unit/localizer_spec.rb +55 -53
  85. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  86. data/spec/unit/namespaced_multiple_example_spec.rb +22 -0
  87. data/spec/unit/override_warning_spec.rb +8 -0
  88. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +453 -449
  89. data/spec/unit/persistence/active_record_persistence_spec.rb +524 -502
  90. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +4 -9
  91. data/spec/unit/persistence/dynamoid_persistence_spec.rb +4 -9
  92. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +83 -9
  93. data/spec/unit/persistence/mongoid_persistence_spec.rb +85 -9
  94. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  95. data/spec/unit/persistence/redis_persistence_spec.rb +8 -32
  96. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +6 -11
  97. data/spec/unit/persistence/sequel_persistence_spec.rb +278 -10
  98. data/spec/unit/simple_multiple_example_spec.rb +28 -0
  99. data/spec/unit/subclassing_multiple_spec.rb +37 -2
  100. data/spec/unit/subclassing_spec.rb +17 -2
  101. data/test/minitest_helper.rb +57 -0
  102. data/test/unit/minitest_matcher_test.rb +80 -0
  103. metadata +99 -28
  104. data/gemfiles/rails_3.2_stable.gemfile +0 -15
  105. data/gemfiles/rails_4.0_mongo_mapper.gemfile +0 -16
  106. data/gemfiles/rails_4.2_mongo_mapper.gemfile +0 -17
  107. data/lib/aasm/persistence/mongo_mapper_persistence.rb +0 -163
  108. data/spec/models/mongo_mapper/no_scope_mongo_mapper.rb +0 -21
  109. data/spec/models/mongo_mapper/simple_mongo_mapper.rb +0 -23
  110. data/spec/models/mongo_mapper/simple_new_dsl_mongo_mapper.rb +0 -25
  111. data/spec/unit/persistence/mongo_mapper_persistence_multiple_spec.rb +0 -149
  112. data/spec/unit/persistence/mongo_mapper_persistence_spec.rb +0 -96
  113. /data/spec/models/{worker.rb → active_record/worker.rb} +0 -0
@@ -1,21 +1,13 @@
1
+ # This file was generated by Appraisal
2
+
1
3
  source "https://rubygems.org"
2
4
 
3
- gem "sqlite3", :platforms => :ruby
4
- gem 'rubysl', :platforms => :rbx
5
- gem 'rubinius-developer_tools', :platforms => :rbx
6
- gem "jruby-openssl", :platforms => :jruby
5
+ gem "sqlite3", :platforms => :ruby
7
6
  gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
8
-
9
- gem "rails", "5.0.0.beta4"
10
-
11
- # mongoid is not yet Rails 5 compatible
12
- # gem 'mongoid', '~>4.0' if Gem::Version.create(RUBY_VERSION.dup) >= Gem::Version.create('1.9.3')
13
-
14
- gem 'sequel'
15
-
16
- # dynamoid is not yet Rails 5 compatible
17
- # gem 'dynamoid', '~> 1', :platforms => :ruby
18
-
19
- gem 'aws-sdk', '~>2', :platforms => :ruby
7
+ gem "rails", "5.0.0"
8
+ gem "mongoid", "~>6.0"
9
+ gem "sequel"
10
+ gem "aws-sdk", "~>2", :platforms => :ruby
11
+ gem "redis-objects"
20
12
 
21
13
  gemspec :path => "../"
data/lib/aasm/aasm.rb CHANGED
@@ -42,7 +42,7 @@ module AASM
42
42
 
43
43
  raise ArgumentError, "The class #{aasm_klass} must inherit from AASM::Base!" unless aasm_klass.ancestors.include?(AASM::Base)
44
44
 
45
- @aasm ||= {}
45
+ @aasm ||= Concurrent::Map.new
46
46
  if @aasm[state_machine_name]
47
47
  # make sure to use provided options
48
48
  options.each do |key, value|
@@ -67,12 +67,12 @@ module AASM
67
67
  unless AASM::StateMachineStore.fetch(self.class, true).machine(name)
68
68
  raise AASM::UnknownStateMachineError.new("There is no state machine with the name '#{name}' defined in #{self.class.name}!")
69
69
  end
70
- @aasm ||= {}
70
+ @aasm ||= Concurrent::Map.new
71
71
  @aasm[name.to_sym] ||= AASM::InstanceBase.new(self, name.to_sym)
72
72
  end
73
73
 
74
74
  def initialize_dup(other)
75
- @aasm = {}
75
+ @aasm = Concurrent::Map.new
76
76
  super
77
77
  end
78
78
 
@@ -150,6 +150,7 @@ private
150
150
  persist_successful = aasm(state_machine_name).set_current_state_with_persistence(new_state_name)
151
151
  if persist_successful
152
152
  yield if block_given?
153
+ event.fire_callbacks(:before_success, self)
153
154
  event.fire_transition_callbacks(self, *process_args(event, old_state.name, *args))
154
155
  event.fire_callbacks(:success, self)
155
156
  end
@@ -158,6 +159,11 @@ private
158
159
  yield if block_given?
159
160
  end
160
161
 
162
+ binding_event = event.options[:binding_event]
163
+ if binding_event
164
+ __send__("#{binding_event}#{'!' if persist}")
165
+ end
166
+
161
167
  if persist_successful
162
168
  old_state.fire_callbacks(:after_exit, self,
163
169
  *process_args(event, aasm(state_machine_name).current_state, *args))
data/lib/aasm/base.rb CHANGED
@@ -130,6 +130,14 @@ module AASM
130
130
  aasm(aasm_name).current_event = event
131
131
  aasm_fire_event(aasm_name, event, {:persist => false}, *args, &block)
132
132
  end
133
+
134
+ # Create aliases for the event methods. Keep the old names to maintain backwards compatibility.
135
+ if namespace?
136
+ klass.send(:alias_method, "may_#{name}_#{namespace}?", "may_#{name}?")
137
+ klass.send(:alias_method, "#{name}_#{namespace}!", "#{name}!")
138
+ klass.send(:alias_method, "#{name}_#{namespace}", name)
139
+ end
140
+
133
141
  end
134
142
 
135
143
  def after_all_transitions(*callbacks, &block)
@@ -208,7 +216,9 @@ module AASM
208
216
  klass.defined_enums.values.any?{ |methods|
209
217
  methods.keys{| enum | enum + '?' == method_name }
210
218
  })
211
- @state_machine.config.logger.warn "#{klass.name}: overriding method '#{method_name}'!"
219
+ unless AASM::Configuration.hide_warnings
220
+ @state_machine.config.logger.warn "#{klass.name}: overriding method '#{method_name}'!"
221
+ end
212
222
  end
213
223
 
214
224
  klass.send(:define_method, method_name, method_definition)
@@ -34,5 +34,9 @@ module AASM
34
34
 
35
35
  # Configure a logger, with default being a Logger to STDERR
36
36
  attr_accessor :logger
37
+
38
+ class << self
39
+ attr_accessor :hide_warnings
40
+ end
37
41
  end
38
42
  end
@@ -22,10 +22,21 @@ module AASM::Core
22
22
  :before_transaction,
23
23
  :ensure,
24
24
  :error,
25
+ :before_success,
25
26
  :success,
26
27
  ], &block) if block
27
28
  end
28
29
 
30
+ # called internally by Ruby 1.9 after clone()
31
+ def initialize_copy(orig)
32
+ super
33
+ @transitions = @transitions.collect { |transition| transition.clone }
34
+ @guards = @guards.dup
35
+ @unless = @unless.dup
36
+ @options = {}
37
+ orig.options.each_pair { |name, setting| @options[name] = setting.is_a?(Hash) || setting.is_a?(Array) ? setting.dup : setting }
38
+ end
39
+
29
40
  # a neutered version of fire - it doesn't actually fire the event, it just
30
41
  # executes the transition guards to determine if a transition is even
31
42
  # an option given current conditions.
@@ -85,7 +96,7 @@ module AASM::Core
85
96
  @transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions.merge(:from => s.to_sym)), &block)
86
97
  end
87
98
  # Create a transition if :to is specified without :from (transitions from ANY state)
88
- if @transitions.empty? && definitions[:to]
99
+ if !definitions[:from] && definitions[:to]
89
100
  @transitions << AASM::Core::Transition.new(self, attach_event_guards(definitions), &block)
90
101
  end
91
102
  end
@@ -122,16 +133,19 @@ module AASM::Core
122
133
  args.unshift(to_state)
123
134
  to_state = nil
124
135
  end
136
+ else
137
+ args.unshift(nil) if args.nil? || args.empty? # If single arg given which is nil, push it back to args
125
138
  end
126
139
 
127
140
  transitions.each do |transition|
128
141
  next if to_state and !Array(transition.to).include?(to_state)
129
- if (options.key?(:may_fire) && Array(transition.to).include?(options[:may_fire])) ||
142
+ if (options.key?(:may_fire) && transition.eql?(options[:may_fire])) ||
130
143
  (!options.key?(:may_fire) && transition.allowed?(obj, *args))
131
- result = to_state || Array(transition.to).first
144
+
132
145
  if options[:test_only]
133
- # result = true
146
+ result = transition
134
147
  else
148
+ result = to_state || Array(transition.to).first
135
149
  Array(transition.to).each {|to| @valid_transitions[to] = transition }
136
150
  transition.execute(obj, *args)
137
151
  end
@@ -9,6 +9,13 @@ module AASM::Core
9
9
  update(options)
10
10
  end
11
11
 
12
+ # called internally by Ruby 1.9 after clone()
13
+ def initialize_copy(orig)
14
+ super
15
+ @options = {}
16
+ orig.options.each_pair { |name, setting| @options[name] = setting.is_a?(Hash) || setting.is_a?(Array) ? setting.dup : setting }
17
+ end
18
+
12
19
  def ==(state)
13
20
  if state.is_a? Symbol
14
21
  name == state
@@ -28,6 +28,15 @@ module AASM::Core
28
28
  @opts = opts
29
29
  end
30
30
 
31
+ # called internally by Ruby 1.9 after clone()
32
+ def initialize_copy(orig)
33
+ super
34
+ @guards = @guards.dup
35
+ @unless = @unless.dup
36
+ @opts = {}
37
+ orig.opts.each_pair { |name, setting| @opts[name] = setting.is_a?(Hash) || setting.is_a?(Array) ? setting.dup : setting }
38
+ end
39
+
31
40
  def allowed?(obj, *args)
32
41
  invoke_callbacks_compatible_with_guard(@guards, obj, args, :guard => true) &&
33
42
  invoke_callbacks_compatible_with_guard(@unless, obj, args, :unless => true)
@@ -60,7 +69,7 @@ module AASM::Core
60
69
 
61
70
  case code
62
71
  when Symbol, String
63
- result = (record.__send__(:method, code.to_sym).arity == 0 ? record.__send__(code) : record.__send__(code, *args))
72
+ result = (record.__send__(:method, code.to_sym).arity != 0 ? record.__send__(code, *args) : record.__send__(code))
64
73
  failures << code unless result
65
74
  result
66
75
  when Proc
@@ -14,7 +14,6 @@ module AASM
14
14
 
15
15
  def current_state=(state)
16
16
  @instance.aasm_write_state_without_persistence(state, @name)
17
- # @current_state = state
18
17
  end
19
18
 
20
19
  def enter_initial_state
@@ -22,7 +21,6 @@ module AASM
22
21
  state_object = state_object_for_name(state_name)
23
22
 
24
23
  state_object.fire_callbacks(:before_enter, @instance)
25
- # state_object.fire_callbacks(:enter, @instance)
26
24
  self.current_state = state_name
27
25
  state_object.fire_callbacks(:after_enter, @instance)
28
26
 
@@ -0,0 +1,13 @@
1
+ module Minitest::Assertions
2
+ def assert_event_allowed(object, event, options = {})
3
+ state_machine_name = options.fetch(:on, :default)
4
+ assert object.aasm(state_machine_name).may_fire_event?(event),
5
+ "Expected that the event :#{event} would be allowed (on :#{state_machine_name})"
6
+ end
7
+
8
+ def refute_event_allowed(object, event, options = {})
9
+ state_machine_name = options.fetch(:on, :default)
10
+ refute object.aasm(state_machine_name).may_fire_event?(event),
11
+ "Expected that the event :#{event} would not be allowed (on :#{state_machine_name})"
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Minitest::Assertions
2
+ def assert_transition_to_allowed(object, to_state, options = {})
3
+ state_machine_name = options.fetch(:on, :default)
4
+ assert object.aasm(state_machine_name).states(permitted: true).include?(to_state),
5
+ "Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
6
+ end
7
+
8
+ def refute_transition_to_allowed(object, to_state, options = {})
9
+ state_machine_name = options.fetch(:on, :default)
10
+ refute object.aasm(state_machine_name).states(permitted: true).include?(to_state),
11
+ "Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Minitest::Assertions
2
+ def assert_have_state(object, state, options = {})
3
+ state_machine_name = options.fetch(:on, :default)
4
+ assert object.aasm(state_machine_name).current_state == state,
5
+ "Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
6
+ end
7
+
8
+ def refute_have_state(object, state, options = {})
9
+ state_machine_name = options.fetch(:on, :default)
10
+ refute object.aasm(state_machine_name).current_state == state,
11
+ "Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Minitest::Assertions
2
+ def assert_transitions_from(object, from_state, *args)
3
+ options = args.first
4
+ options[:on] ||= :default
5
+ assert _transitions_from?(object, from_state, args, options),
6
+ "Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
7
+ end
8
+
9
+ def refute_transitions_from(object, from_state, *args)
10
+ options = args.first
11
+ options[:on] ||= :default
12
+ refute _transitions_from?(object, from_state, args, options),
13
+ "Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
14
+ end
15
+
16
+ def _transitions_from?(object, from_state, args, options)
17
+ state_machine_name = options[:on]
18
+ object.aasm(state_machine_name).current_state = from_state.to_sym
19
+ object.send(options[:on_event], *args) && options[:to].to_sym == object.aasm(state_machine_name).current_state
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ Minitest = MiniTest unless defined? Minitest
2
+ # relative-require all minitest_spec files
3
+ Dir[File.dirname(__FILE__) + '/minitest/*.rb'].each do |file|
4
+ require 'aasm/minitest/' + File.basename(file, File.extname(file))
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'aasm/minitest'
2
+
3
+ module Minitest::Expectations
4
+ AASM.infect_an_assertion :assert_transitions_from, :must_transition_from, :do_not_flip
5
+ AASM.infect_an_assertion :refute_transitions_from, :wont_transition_from, :do_not_flip
6
+
7
+ AASM.infect_an_assertion :assert_transition_to_allowed, :must_allow_transition_to, :do_not_flip
8
+ AASM.infect_an_assertion :refute_transition_to_allowed, :wont_allow_transition_to, :do_not_flip
9
+
10
+ AASM.infect_an_assertion :assert_have_state, :must_have_state, :do_not_flip
11
+ AASM.infect_an_assertion :refute_have_state, :wont_have_state, :do_not_flip
12
+
13
+ AASM.infect_an_assertion :assert_event_allowed, :must_allow_event, :do_not_flip
14
+ AASM.infect_an_assertion :refute_event_allowed, :wont_allow_event, :do_not_flip
15
+ end
@@ -1,3 +1,4 @@
1
+ require 'aasm/persistence/orm'
1
2
  module AASM
2
3
  module Persistence
3
4
  module ActiveRecordPersistence
@@ -28,6 +29,7 @@ module AASM
28
29
  #
29
30
  def self.included(base)
30
31
  base.send(:include, AASM::Persistence::Base)
32
+ base.send(:include, AASM::Persistence::ORM)
31
33
  base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
32
34
  base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
33
35
 
@@ -56,67 +58,41 @@ module AASM
56
58
 
57
59
  module InstanceMethods
58
60
 
59
- # Writes <tt>state</tt> to the state column and persists it to the database
60
- #
61
- # foo = Foo.find(1)
62
- # foo.aasm.current_state # => :opened
63
- # foo.close!
64
- # foo.aasm.current_state # => :closed
65
- # Foo.find(1).aasm.current_state # => :closed
66
- #
67
- # NOTE: intended to be called from an event
68
- def aasm_write_state(state, name=:default)
69
- old_value = read_attribute(self.class.aasm(name).attribute_name)
70
- aasm_write_attribute state, name
71
-
72
- success = if aasm_skipping_validations(name)
73
- value = aasm_raw_attribute_value(state, name)
74
- aasm_update_column(name, value)
75
- else
76
- self.save
77
- end
61
+ private
78
62
 
79
- unless success
80
- aasm_rollback(name, old_value)
81
- raise ActiveRecord::RecordInvalid.new(self) if aasm_whiny_persistence(name)
82
- end
63
+ def aasm_raise_invalid_record
64
+ raise ActiveRecord::RecordInvalid.new(self)
65
+ end
83
66
 
84
- success
67
+ def aasm_save
68
+ self.save
85
69
  end
86
70
 
87
- # Writes <tt>state</tt> to the state column, but does not persist it to the database
88
- #
89
- # foo = Foo.find(1)
90
- # foo.aasm.current_state # => :opened
91
- # foo.close
92
- # foo.aasm.current_state # => :closed
93
- # Foo.find(1).aasm.current_state # => :opened
94
- # foo.save
95
- # foo.aasm.current_state # => :closed
96
- # Foo.find(1).aasm.current_state # => :closed
97
- #
98
- # NOTE: intended to be called from an event
99
- def aasm_write_state_without_persistence(state, name=:default)
100
- aasm_write_attribute(state, name)
71
+ def aasm_update_column(attribute_name, value)
72
+ self.class.unscoped.where(self.class.primary_key => self.id).update_all(attribute_name => value) == 1
101
73
  end
102
74
 
103
- private
75
+ def aasm_read_attribute(name)
76
+ read_attribute(name)
77
+ end
104
78
 
105
- def aasm_update_column(name, value)
106
- self.class.where(self.class.primary_key => self.id).update_all(self.class.aasm(name).attribute_name => value) == 1
79
+ def aasm_write_attribute(name, value)
80
+ write_attribute(name, value)
107
81
  end
108
82
 
109
- def aasm_rollback(name, old_value)
110
- write_attribute(self.class.aasm(name).attribute_name, old_value)
111
- false
83
+ def aasm_transaction(requires_new, requires_lock)
84
+ self.class.transaction(:requires_new => requires_new) do
85
+ lock!(requires_lock) if requires_lock
86
+ yield
87
+ end
112
88
  end
113
89
 
114
90
  def aasm_enum(name=:default)
115
91
  case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
116
- when false then nil
117
- when true then aasm_guess_enum_method(name)
118
- when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
119
- else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
92
+ when false then nil
93
+ when true then aasm_guess_enum_method(name)
94
+ when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
95
+ else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
120
96
  end
121
97
  end
122
98
 
@@ -131,23 +107,11 @@ module AASM
131
107
  self.class.aasm(name).attribute_name.to_s.pluralize.to_sym
132
108
  end
133
109
 
134
- def aasm_skipping_validations(state_machine_name)
135
- AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
136
- end
137
-
138
- def aasm_whiny_persistence(state_machine_name)
139
- AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.whiny_persistence
140
- end
141
-
142
- def aasm_write_attribute(state, name=:default)
143
- write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
144
- end
145
-
146
110
  def aasm_raw_attribute_value(state, name=:default)
147
111
  if aasm_enum(name)
148
112
  self.class.send(aasm_enum(name))[state]
149
113
  else
150
- state.to_s
114
+ super
151
115
  end
152
116
  end
153
117
 
@@ -179,46 +143,6 @@ module AASM
179
143
  attribute_names.include?(attribute_name.to_s) && send(attribute_name).blank?
180
144
  end
181
145
 
182
- def aasm_fire_event(state_machine_name, name, options, *args, &block)
183
- event = self.class.aasm(state_machine_name).state_machine.events[name]
184
-
185
- if options[:persist]
186
- event.fire_callbacks(:before_transaction, self, *args)
187
- event.fire_global_callbacks(:before_all_transactions, self, *args)
188
- end
189
-
190
- begin
191
- success = if options[:persist]
192
- self.class.transaction(:requires_new => requires_new?(state_machine_name)) do
193
- lock!(requires_lock?(state_machine_name)) if requires_lock?(state_machine_name)
194
- super
195
- end
196
- else
197
- super
198
- end
199
-
200
- if options[:persist] && success
201
- event.fire_callbacks(:after_commit, self, *args)
202
- event.fire_global_callbacks(:after_all_commits, self, *args)
203
- end
204
- ensure
205
- if options[:persist]
206
- event.fire_callbacks(:after_transaction, self, *args)
207
- event.fire_global_callbacks(:after_all_transactions, self, *args)
208
- end
209
- end
210
-
211
- success
212
- end
213
-
214
- def requires_new?(state_machine_name)
215
- AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_new_transaction
216
- end
217
-
218
- def requires_lock?(state_machine_name)
219
- AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_lock
220
- end
221
-
222
146
  def aasm_validate_states
223
147
  AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
224
148
  unless aasm_skipping_validations(state_machine_name)
@@ -34,13 +34,17 @@ module AASM
34
34
  # This allows for nil aasm states - be sure to add validation to your model
35
35
  def aasm_read_state(name=:default)
36
36
  state = send(self.class.aasm(name).attribute_name)
37
- if new_record?
38
- state.blank? ? aasm(name).determine_state_name(self.class.aasm(name).initial_state) : state.to_sym
37
+ if state.blank?
38
+ aasm_new_record? ? aasm(name).determine_state_name(self.class.aasm(name).initial_state) : nil
39
39
  else
40
- state.blank? ? nil : state.to_sym
40
+ state.to_sym
41
41
  end
42
42
  end
43
43
 
44
+ def aasm_new_record?
45
+ new_record?
46
+ end
47
+
44
48
  module ClassMethods
45
49
  def aasm_column(attribute_name=nil)
46
50
  warn "[DEPRECATION] aasm_column is deprecated. Use aasm.attribute_name instead"
@@ -1,3 +1,4 @@
1
+ require 'aasm/persistence/orm'
1
2
  module AASM
2
3
  module Persistence
3
4
  module MongoidPersistence
@@ -30,6 +31,7 @@ module AASM
30
31
  #
31
32
  def self.included(base)
32
33
  base.send(:include, AASM::Persistence::Base)
34
+ base.send(:include, AASM::Persistence::ORM)
33
35
  base.send(:include, AASM::Persistence::MongoidPersistence::InstanceMethods)
34
36
  base.extend AASM::Persistence::MongoidPersistence::ClassMethods
35
37
 
@@ -50,45 +52,37 @@ module AASM
50
52
 
51
53
  module InstanceMethods
52
54
 
53
- # Writes <tt>state</tt> to the state column and persists it to the database
54
- # using update_attribute (which bypasses validation)
55
- #
56
- # foo = Foo.find(1)
57
- # foo.aasm.current_state # => :opened
58
- # foo.close!
59
- # foo.aasm.current_state # => :closed
60
- # Foo.find(1).aasm.current_state # => :closed
61
- #
62
- # NOTE: intended to be called from an event
63
- def aasm_write_state(state, name=:default)
64
- old_value = read_attribute(self.class.aasm(name).attribute_name)
65
- write_attribute(self.class.aasm(name).attribute_name, state.to_s)
55
+ private
56
+
57
+ def aasm_save
58
+ self.save
59
+ end
60
+
61
+ def aasm_raise_invalid_record
62
+ raise Mongoid::Errors::Validations.new(self)
63
+ end
66
64
 
67
- unless self.save(:validate => false)
68
- write_attribute(self.class.aasm(name).attribute_name, old_value)
69
- return false
65
+ def aasm_supports_transactions?
66
+ false
67
+ end
68
+
69
+ def aasm_update_column(attribute_name, value)
70
+ if Mongoid::VERSION.to_f >= 4
71
+ set(Hash[attribute_name, value])
72
+ else
73
+ set(attribute_name, value)
70
74
  end
71
75
 
72
76
  true
73
77
  end
74
78
 
75
- # Writes <tt>state</tt> to the state column, but does not persist it to the database
76
- #
77
- # foo = Foo.find(1)
78
- # foo.aasm.current_state # => :opened
79
- # foo.close
80
- # foo.aasm.current_state # => :closed
81
- # Foo.find(1).aasm.current_state # => :opened
82
- # foo.save
83
- # foo.aasm.current_state # => :closed
84
- # Foo.find(1).aasm.current_state # => :closed
85
- #
86
- # NOTE: intended to be called from an event
87
- def aasm_write_state_without_persistence(state, name=:default)
88
- write_attribute(self.class.aasm(name).attribute_name, state.to_s)
79
+ def aasm_read_attribute(name)
80
+ read_attribute(name)
89
81
  end
90
82
 
91
- private
83
+ def aasm_write_attribute(name, value)
84
+ write_attribute(name, value)
85
+ end
92
86
 
93
87
  # Ensures that if the aasm_state column is nil and the record is new
94
88
  # that the initial state gets populated before validation on create