micro-max-box 0.0.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 (55) hide show
  1. checksums.yaml +7 -0
  2. data/aasm-6.0.0/CHANGELOG.md +497 -0
  3. data/aasm-6.0.0/LICENSE +20 -0
  4. data/aasm-6.0.0/README.md +1534 -0
  5. data/aasm-6.0.0/lib/aasm/aasm.rb +208 -0
  6. data/aasm-6.0.0/lib/aasm/base.rb +300 -0
  7. data/aasm-6.0.0/lib/aasm/configuration.rb +48 -0
  8. data/aasm-6.0.0/lib/aasm/core/event.rb +178 -0
  9. data/aasm-6.0.0/lib/aasm/core/invoker.rb +129 -0
  10. data/aasm-6.0.0/lib/aasm/core/invokers/base_invoker.rb +85 -0
  11. data/aasm-6.0.0/lib/aasm/core/invokers/class_invoker.rb +75 -0
  12. data/aasm-6.0.0/lib/aasm/core/invokers/literal_invoker.rb +90 -0
  13. data/aasm-6.0.0/lib/aasm/core/invokers/proc_invoker.rb +94 -0
  14. data/aasm-6.0.0/lib/aasm/core/state.rb +91 -0
  15. data/aasm-6.0.0/lib/aasm/core/transition.rb +83 -0
  16. data/aasm-6.0.0/lib/aasm/dsl_helper.rb +32 -0
  17. data/aasm-6.0.0/lib/aasm/errors.rb +22 -0
  18. data/aasm-6.0.0/lib/aasm/instance_base.rb +153 -0
  19. data/aasm-6.0.0/lib/aasm/localizer.rb +64 -0
  20. data/aasm-6.0.0/lib/aasm/minitest/allow_event.rb +13 -0
  21. data/aasm-6.0.0/lib/aasm/minitest/allow_transition_to.rb +13 -0
  22. data/aasm-6.0.0/lib/aasm/minitest/have_state.rb +13 -0
  23. data/aasm-6.0.0/lib/aasm/minitest/transition_from.rb +21 -0
  24. data/aasm-6.0.0/lib/aasm/minitest.rb +5 -0
  25. data/aasm-6.0.0/lib/aasm/minitest_spec.rb +15 -0
  26. data/aasm-6.0.0/lib/aasm/persistence/active_record_persistence.rb +174 -0
  27. data/aasm-6.0.0/lib/aasm/persistence/base.rb +89 -0
  28. data/aasm-6.0.0/lib/aasm/persistence/core_data_query_persistence.rb +94 -0
  29. data/aasm-6.0.0/lib/aasm/persistence/dynamoid_persistence.rb +92 -0
  30. data/aasm-6.0.0/lib/aasm/persistence/mongoid_persistence.rb +126 -0
  31. data/aasm-6.0.0/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  32. data/aasm-6.0.0/lib/aasm/persistence/orm.rb +154 -0
  33. data/aasm-6.0.0/lib/aasm/persistence/plain_persistence.rb +26 -0
  34. data/aasm-6.0.0/lib/aasm/persistence/redis_persistence.rb +112 -0
  35. data/aasm-6.0.0/lib/aasm/persistence/sequel_persistence.rb +83 -0
  36. data/aasm-6.0.0/lib/aasm/persistence.rb +54 -0
  37. data/aasm-6.0.0/lib/aasm/rspec/allow_event.rb +26 -0
  38. data/aasm-6.0.0/lib/aasm/rspec/allow_transition_to.rb +26 -0
  39. data/aasm-6.0.0/lib/aasm/rspec/have_state.rb +22 -0
  40. data/aasm-6.0.0/lib/aasm/rspec/transition_from.rb +36 -0
  41. data/aasm-6.0.0/lib/aasm/rspec.rb +5 -0
  42. data/aasm-6.0.0/lib/aasm/state_machine.rb +53 -0
  43. data/aasm-6.0.0/lib/aasm/state_machine_store.rb +77 -0
  44. data/aasm-6.0.0/lib/aasm/version.rb +3 -0
  45. data/aasm-6.0.0/lib/aasm.rb +21 -0
  46. data/aasm-6.0.0/lib/generators/aasm/aasm_generator.rb +16 -0
  47. data/aasm-6.0.0/lib/generators/aasm/orm_helpers.rb +41 -0
  48. data/aasm-6.0.0/lib/generators/active_record/aasm_generator.rb +40 -0
  49. data/aasm-6.0.0/lib/generators/active_record/templates/migration.rb +8 -0
  50. data/aasm-6.0.0/lib/generators/active_record/templates/migration_existing.rb +5 -0
  51. data/aasm-6.0.0/lib/generators/mongoid/aasm_generator.rb +28 -0
  52. data/aasm-6.0.0/lib/generators/nobrainer/aasm_generator.rb +28 -0
  53. data/aasm-6.0.0/lib/motion-aasm.rb +37 -0
  54. data/micro-max-box.gemspec +12 -0
  55. metadata +94 -0
@@ -0,0 +1,174 @@
1
+ require 'aasm/persistence/orm'
2
+ module AASM
3
+ module Persistence
4
+ module ActiveRecordPersistence
5
+ # This method:
6
+ #
7
+ # * extends the model with ClassMethods
8
+ # * includes InstanceMethods
9
+ #
10
+ # Adds
11
+ #
12
+ # after_initialize :aasm_ensure_initial_state
13
+ #
14
+ # As a result, it doesn't matter when you define your methods - the following 2 are equivalent
15
+ #
16
+ # class Foo < ActiveRecord::Base
17
+ # def aasm_write_state(state)
18
+ # "bar"
19
+ # end
20
+ # include AASM
21
+ # end
22
+ #
23
+ # class Foo < ActiveRecord::Base
24
+ # include AASM
25
+ # def aasm_write_state(state)
26
+ # "bar"
27
+ # end
28
+ # end
29
+ #
30
+ def self.included(base)
31
+ base.send(:include, AASM::Persistence::Base)
32
+ base.send(:include, AASM::Persistence::ORM)
33
+ base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
34
+ base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
35
+
36
+ base.after_initialize :aasm_ensure_initial_state
37
+
38
+ # ensure state is in the list of states
39
+ base.validate :aasm_validate_states
40
+ end
41
+
42
+ module ClassMethods
43
+ def aasm_create_scope(state_machine_name, scope_name)
44
+ conditions = { aasm(state_machine_name).attribute_name => scope_name.to_s }
45
+ class_eval do
46
+ scope scope_name, lambda { where(table_name => conditions) }
47
+ end
48
+ end
49
+ end
50
+
51
+ module InstanceMethods
52
+
53
+ private
54
+
55
+ def aasm_execute_after_commit
56
+ begin
57
+ require 'after_commit_everywhere'
58
+ raise LoadError unless Gem::Version.new(::AfterCommitEverywhere::VERSION) >= Gem::Version.new('0.1.5')
59
+
60
+ self.extend ::AfterCommitEverywhere
61
+ after_commit do
62
+ yield
63
+ end
64
+ rescue LoadError
65
+ warn <<-MSG
66
+ [DEPRECATION] :after_commit AASM callback is not safe in terms of race conditions and redundant calls.
67
+ Please add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile in order to fix that.
68
+ MSG
69
+ yield
70
+ end
71
+ end
72
+
73
+ def aasm_raise_invalid_record
74
+ raise ActiveRecord::RecordInvalid.new(self)
75
+ end
76
+
77
+ def aasm_save
78
+ self.save
79
+ end
80
+
81
+ def aasm_update_column(attribute_name, value)
82
+ self.class.unscoped.where(self.class.primary_key => self.id).update_all(attribute_name => value) == 1
83
+ end
84
+
85
+ def aasm_read_attribute(name)
86
+ read_attribute(name)
87
+ end
88
+
89
+ def aasm_write_attribute(name, value)
90
+ write_attribute(name, value)
91
+ end
92
+
93
+ def aasm_transaction(requires_new, requires_lock)
94
+ self.class.transaction(:requires_new => requires_new) do
95
+ lock!(requires_lock) if requires_lock
96
+ yield
97
+ end
98
+ end
99
+
100
+ def aasm_enum(name=:default)
101
+ case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
102
+ when false then nil
103
+ when true then aasm_guess_enum_method(name)
104
+ when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
105
+ else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
106
+ end
107
+ end
108
+
109
+ def aasm_column_looks_like_enum(name=:default)
110
+ column_name = self.class.aasm(name).attribute_name.to_s
111
+ column = self.class.columns_hash[column_name]
112
+ raise NoMethodError.new("undefined method '#{column_name}' for #{self.class}") if column.nil?
113
+ column.type == :integer
114
+ end
115
+
116
+ def aasm_guess_enum_method(name=:default)
117
+ self.class.aasm(name).attribute_name.to_s.pluralize.to_sym
118
+ end
119
+
120
+ def aasm_raw_attribute_value(state, name=:default)
121
+ if aasm_enum(name)
122
+ self.class.send(aasm_enum(name))[state]
123
+ else
124
+ super
125
+ end
126
+ end
127
+
128
+ # Ensures that if the aasm_state column is nil and the record is new
129
+ # then the initial state gets populated after initialization
130
+ #
131
+ # foo = Foo.new
132
+ # foo.aasm_state # => "open" (where :open is the initial state)
133
+ #
134
+ #
135
+ # foo = Foo.find(:first)
136
+ # foo.aasm_state # => 1
137
+ # foo.aasm_state = nil
138
+ # foo.valid?
139
+ # foo.aasm_state # => nil
140
+ #
141
+ def aasm_ensure_initial_state
142
+ AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
143
+ # checking via respond_to? does not work in Rails <= 3
144
+ # if respond_to?(self.class.aasm(state_machine_name).attribute_name) && send(self.class.aasm(state_machine_name).attribute_name).blank? # Rails 4
145
+ if aasm_column_is_blank?(state_machine_name)
146
+ aasm(state_machine_name).enter_initial_state
147
+ end
148
+ end
149
+ end
150
+
151
+ def aasm_column_is_blank?(state_machine_name)
152
+ attribute_name = self.class.aasm(state_machine_name).attribute_name
153
+ attribute_names.include?(attribute_name.to_s) &&
154
+ (send(attribute_name).respond_to?(:empty?) ? !!send(attribute_name).empty? : !send(attribute_name))
155
+ end
156
+
157
+ def aasm_validate_states
158
+ AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
159
+ unless aasm_skipping_validations(state_machine_name)
160
+ if aasm_invalid_state?(state_machine_name)
161
+ self.errors.add(AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.column , "is invalid")
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ def aasm_invalid_state?(state_machine_name)
168
+ aasm(state_machine_name).current_state && !aasm(state_machine_name).states.include?(aasm(state_machine_name).current_state)
169
+ end
170
+ end # InstanceMethods
171
+
172
+ end
173
+ end # Persistence
174
+ end # AASM
@@ -0,0 +1,89 @@
1
+ module AASM
2
+ module Persistence
3
+ module Base
4
+
5
+ def self.included(base) #:nodoc:
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ # Returns the value of the aasm.attribute_name - called from <tt>aasm.current_state</tt>
10
+ #
11
+ # If it's a new record, and the aasm state column is blank it returns the initial state
12
+ # (example provided here for ActiveRecord, but it's true for Mongoid as well):
13
+ #
14
+ # class Foo < ActiveRecord::Base
15
+ # include AASM
16
+ # aasm :column => :status do
17
+ # state :opened
18
+ # state :closed
19
+ # end
20
+ # end
21
+ #
22
+ # foo = Foo.new
23
+ # foo.current_state # => :opened
24
+ # foo.close
25
+ # foo.current_state # => :closed
26
+ #
27
+ # foo = Foo.find(1)
28
+ # foo.current_state # => :opened
29
+ # foo.aasm_state = nil
30
+ # foo.current_state # => nil
31
+ #
32
+ # NOTE: intended to be called from an event
33
+ #
34
+ # This allows for nil aasm states - be sure to add validation to your model
35
+ def aasm_read_state(name=:default)
36
+ state = send(self.class.aasm(name).attribute_name)
37
+ if !state || state.empty?
38
+ aasm_new_record? ? aasm(name).determine_state_name(self.class.aasm(name).initial_state) : nil
39
+ else
40
+ state.to_sym
41
+ end
42
+ end
43
+
44
+ def aasm_new_record?
45
+ new_record?
46
+ end
47
+
48
+ module ClassMethods
49
+ def aasm_column(attribute_name=nil)
50
+ warn "[DEPRECATION] aasm_column is deprecated. Use aasm.attribute_name instead"
51
+ aasm.attribute_name(attribute_name)
52
+ end
53
+ end # ClassMethods
54
+
55
+ end # Base
56
+ end # Persistence
57
+
58
+ class Base
59
+ # make sure to create a (named) scope for each state
60
+ def state_with_scope(*args)
61
+ names = state_without_scope(*args)
62
+ names.each do |name|
63
+ create_scopes(name)
64
+ end
65
+ end
66
+ alias_method :state_without_scope, :state
67
+ alias_method :state, :state_with_scope
68
+
69
+ private
70
+
71
+ def create_scope?(name)
72
+ @state_machine.config.create_scopes && !@klass.respond_to?(name) && @klass.respond_to?(:aasm_create_scope)
73
+ end
74
+
75
+ def create_scope(name)
76
+ @klass.aasm_create_scope(@name, name) if create_scope?(name)
77
+ end
78
+
79
+ def create_scopes(name)
80
+ if namespace?
81
+ # Create default scopes even when namespace? for backward compatibility
82
+ namepaced_name = "#{namespace}_#{name}"
83
+ create_scope(namepaced_name)
84
+ end
85
+ create_scope(name)
86
+ end
87
+ end # Base
88
+
89
+ end # AASM
@@ -0,0 +1,94 @@
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
+ next if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
81
+ send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
82
+ end
83
+ end
84
+ end # InstanceMethods
85
+
86
+ # module NamedScopeMethods
87
+ # def aasm_state_with_named_scope name, options = {}
88
+ # aasm_state_without_named_scope name, options
89
+ # self.named_scope name, :conditions => { "#{table_name}.#{self.aasm.attribute_name}" => name.to_s} unless self.respond_to?(name)
90
+ # end
91
+ # end
92
+ end
93
+ end # Persistence
94
+ end # AASM
@@ -0,0 +1,92 @@
1
+ module AASM
2
+ module Persistence
3
+ module DynamoidPersistence
4
+ def self.included(base)
5
+ base.send(:include, AASM::Persistence::Base)
6
+ base.send(:include, AASM::Persistence::DynamoidPersistence::InstanceMethods)
7
+
8
+ base.after_initialize :aasm_ensure_initial_state
9
+
10
+ # Because Dynamoid only use define_method to add attribute assignment method in Class.
11
+ #
12
+ # In AASM::Base.initialize, it redefines and calls super in this method without superclass method.
13
+ # We override method_missing to solve this problem.
14
+ #
15
+ base.class_eval %Q(
16
+ def method_missing(method_name, *arguments, &block)
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
18
+ attribute_name = method_name.to_s.gsub("=", '')
19
+ write_attribute(attribute_name.to_sym, *arguments)
20
+ else
21
+ super
22
+ end
23
+ end
24
+ )
25
+ end
26
+
27
+ module InstanceMethods
28
+
29
+ # Writes <tt>state</tt> to the state column and persists it to the database
30
+ # using update_attribute (which bypasses validation)
31
+ #
32
+ # foo = Foo.find(1)
33
+ # foo.aasm.current_state # => :opened
34
+ # foo.close!
35
+ # foo.aasm.current_state # => :closed
36
+ # Foo.find(1).aasm.current_state # => :closed
37
+ #
38
+ # NOTE: intended to be called from an event
39
+ def aasm_write_state(state, name=:default)
40
+ old_value = read_attribute(self.class.aasm(name).attribute_name)
41
+ write_attribute(self.class.aasm(name).attribute_name, state.to_s)
42
+
43
+ unless self.save(:validate => false)
44
+ write_attribute(self.class.aasm(name).attribute_name, old_value)
45
+ return false
46
+ end
47
+
48
+ true
49
+ end
50
+
51
+ # Writes <tt>state</tt> to the state column, but does not persist it to the database
52
+ #
53
+ # foo = Foo.find(1)
54
+ # foo.aasm.current_state # => :opened
55
+ # foo.close
56
+ # foo.aasm.current_state # => :closed
57
+ # Foo.find(1).aasm.current_state # => :opened
58
+ # foo.save
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_without_persistence(state, name=:default)
64
+ write_attribute(self.class.aasm(name).attribute_name, state.to_s)
65
+ end
66
+
67
+ private
68
+
69
+ # Ensures that if the aasm_state column is nil and the record is new
70
+ # that the initial state gets populated before validation on create
71
+ #
72
+ # foo = Foo.new
73
+ # foo.aasm_state # => nil
74
+ # foo.valid?
75
+ # foo.aasm_state # => "open" (where :open is the initial state)
76
+ #
77
+ #
78
+ # foo = Foo.find(:first)
79
+ # foo.aasm_state # => 1
80
+ # foo.aasm_state = nil
81
+ # foo.valid?
82
+ # foo.aasm_state # => nil
83
+ #
84
+ def aasm_ensure_initial_state
85
+ AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
86
+ aasm(state_machine_name).enter_initial_state if !send(self.class.aasm(state_machine_name).attribute_name) || send(self.class.aasm(state_machine_name).attribute_name).empty?
87
+ end
88
+ end
89
+ end # InstanceMethods
90
+ end
91
+ end # Persistence
92
+ end # AASM
@@ -0,0 +1,126 @@
1
+ require 'aasm/persistence/orm'
2
+ module AASM
3
+ module Persistence
4
+ module MongoidPersistence
5
+ # This method:
6
+ #
7
+ # * extends the model with ClassMethods
8
+ # * includes InstanceMethods
9
+ #
10
+ # Adds
11
+ #
12
+ # before_validation :aasm_ensure_initial_state
13
+ #
14
+ # As a result, it doesn't matter when you define your methods - the following 2 are equivalent
15
+ #
16
+ # class Foo
17
+ # include Mongoid::Document
18
+ # def aasm_write_state(state)
19
+ # "bar"
20
+ # end
21
+ # include AASM
22
+ # end
23
+ #
24
+ # class Foo
25
+ # include Mongoid::Document
26
+ # include AASM
27
+ # def aasm_write_state(state)
28
+ # "bar"
29
+ # end
30
+ # end
31
+ #
32
+ def self.included(base)
33
+ base.send(:include, AASM::Persistence::Base)
34
+ base.send(:include, AASM::Persistence::ORM)
35
+ base.send(:include, AASM::Persistence::MongoidPersistence::InstanceMethods)
36
+ base.extend AASM::Persistence::MongoidPersistence::ClassMethods
37
+
38
+ base.after_initialize :aasm_ensure_initial_state
39
+ end
40
+
41
+ module ClassMethods
42
+ def aasm_create_scope(state_machine_name, scope_name)
43
+ scope_options = lambda {
44
+ send(
45
+ :where,
46
+ { aasm(state_machine_name).attribute_name.to_sym => scope_name.to_s }
47
+ )
48
+ }
49
+ send(:scope, scope_name, scope_options)
50
+ end
51
+ end
52
+
53
+ module InstanceMethods
54
+
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
64
+
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)
74
+ end
75
+
76
+ true
77
+ end
78
+
79
+ def aasm_read_attribute(name)
80
+ read_attribute(name)
81
+ end
82
+
83
+ def aasm_write_attribute(name, value)
84
+ write_attribute(name, value)
85
+ end
86
+
87
+ # Ensures that if the aasm_state column is nil and the record is new
88
+ # that the initial state gets populated before validation on create
89
+ #
90
+ # foo = Foo.new
91
+ # foo.aasm_state # => nil
92
+ # foo.valid?
93
+ # foo.aasm_state # => "open" (where :open is the initial state)
94
+ #
95
+ #
96
+ # foo = Foo.find(:first)
97
+ # foo.aasm_state # => 1
98
+ # foo.aasm_state = nil
99
+ # foo.valid?
100
+ # foo.aasm_state # => nil
101
+ #
102
+ def aasm_ensure_initial_state
103
+ AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
104
+ attribute_name = self.class.aasm(state_machine_name).attribute_name.to_s
105
+ # Do not load initial state when object attributes are not loaded,
106
+ # mongoid has_many relationship does not load child object attributes when
107
+ # only ids are loaded, for example parent.child_ids will not load child object attributes.
108
+ # This feature is introduced in mongoid > 4.
109
+ if attribute_names.include?(attribute_name) && !attributes[attribute_name] || attributes[attribute_name].empty?
110
+ # attribute_missing? is defined in mongoid > 4
111
+ return if Mongoid::VERSION.to_f >= 4 && attribute_missing?(attribute_name)
112
+ send("#{self.class.aasm(state_machine_name).attribute_name}=", aasm(state_machine_name).enter_initial_state.to_s)
113
+ end
114
+ end
115
+ end
116
+ end # InstanceMethods
117
+
118
+ # module NamedScopeMethods
119
+ # def aasm_state_with_named_scope name, options = {}
120
+ # aasm_state_without_named_scope name, options
121
+ # self.named_scope name, :conditions => { "#{table_name}.#{self.aasm.attribute_name}" => name.to_s} unless self.respond_to?(name)
122
+ # end
123
+ # end
124
+ end
125
+ end # Persistence
126
+ end # AASM
@@ -0,0 +1,105 @@
1
+ require 'aasm/persistence/orm'
2
+ module AASM
3
+ module Persistence
4
+ module NoBrainerPersistence
5
+ # This method:
6
+ #
7
+ # * extends the model with ClassMethods
8
+ # * includes InstanceMethods
9
+ #
10
+ # Adds
11
+ #
12
+ # before_validation :aasm_ensure_initial_state
13
+ #
14
+ # As a result, it doesn't matter when you define your methods - the following 2 are equivalent
15
+ #
16
+ # class Foo
17
+ # include NoBrainer::Document
18
+ # def aasm_write_state(state)
19
+ # "bar"
20
+ # end
21
+ # include AASM
22
+ # end
23
+ #
24
+ # class Foo
25
+ # include NoBrainer::Document
26
+ # include AASM
27
+ # def aasm_write_state(state)
28
+ # "bar"
29
+ # end
30
+ # end
31
+ #
32
+ def self.included(base)
33
+ base.send(:include, AASM::Persistence::Base)
34
+ base.send(:include, AASM::Persistence::ORM)
35
+ base.send(:include, AASM::Persistence::NoBrainerPersistence::InstanceMethods)
36
+ base.extend AASM::Persistence::NoBrainerPersistence::ClassMethods
37
+
38
+ base.after_initialize :aasm_ensure_initial_state
39
+ end
40
+
41
+ module ClassMethods
42
+ def aasm_create_scope(state_machine_name, scope_name)
43
+ scope_options = lambda {
44
+ where(aasm(state_machine_name).attribute_name.to_sym => scope_name.to_s)
45
+ }
46
+ send(:scope, scope_name, scope_options)
47
+ end
48
+ end
49
+
50
+ module InstanceMethods
51
+
52
+ private
53
+
54
+ def aasm_save
55
+ self.save
56
+ end
57
+
58
+ def aasm_raise_invalid_record
59
+ raise NoBrainer::Error::DocumentInvalid.new(self)
60
+ end
61
+
62
+ def aasm_supports_transactions?
63
+ false
64
+ end
65
+
66
+ def aasm_update_column(attribute_name, value)
67
+ write_attribute(attribute_name, value)
68
+ save(validate: false)
69
+
70
+ true
71
+ end
72
+
73
+ def aasm_read_attribute(name)
74
+ read_attribute(name)
75
+ end
76
+
77
+ def aasm_write_attribute(name, value)
78
+ write_attribute(name, value)
79
+ end
80
+
81
+ # Ensures that if the aasm_state column is nil and the record is new
82
+ # that the initial state gets populated before validation on create
83
+ #
84
+ # foo = Foo.new
85
+ # foo.aasm_state # => nil
86
+ # foo.valid?
87
+ # foo.aasm_state # => "open" (where :open is the initial state)
88
+ #
89
+ #
90
+ # foo = Foo.find(:first)
91
+ # foo.aasm_state # => 1
92
+ # foo.aasm_state = nil
93
+ # foo.valid?
94
+ # foo.aasm_state # => nil
95
+ #
96
+ def aasm_ensure_initial_state
97
+ AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
98
+ aasm_column = self.class.aasm(name).attribute_name
99
+ aasm(name).enter_initial_state if !read_attribute(aasm_column) || read_attribute(aasm_column).empty?
100
+ end
101
+ end
102
+ end # InstanceMethods
103
+ end
104
+ end # Persistence
105
+ end # AASM