aasm 2.1.1 → 5.2.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.
Files changed (275) hide show
  1. checksums.yaml +7 -0
  2. data/.document +6 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.gitignore +20 -0
  6. data/.travis.yml +82 -0
  7. data/API +34 -0
  8. data/Appraisals +67 -0
  9. data/CHANGELOG.md +453 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +24 -0
  12. data/Dockerfile +44 -0
  13. data/Gemfile +6 -0
  14. data/Gemfile.lock_old +151 -0
  15. data/HOWTO +12 -0
  16. data/{MIT-LICENSE → LICENSE} +1 -1
  17. data/PLANNED_CHANGES.md +11 -0
  18. data/README.md +1524 -0
  19. data/README_FROM_VERSION_3_TO_4.md +240 -0
  20. data/Rakefile +20 -84
  21. data/TESTING.md +25 -0
  22. data/aasm.gemspec +37 -0
  23. data/docker-compose.yml +40 -0
  24. data/gemfiles/norails.gemfile +10 -0
  25. data/gemfiles/rails_4.2.gemfile +17 -0
  26. data/gemfiles/rails_4.2_mongoid_5.gemfile +12 -0
  27. data/gemfiles/rails_4.2_nobrainer.gemfile +9 -0
  28. data/gemfiles/rails_5.0.gemfile +14 -0
  29. data/gemfiles/rails_5.0_nobrainer.gemfile +9 -0
  30. data/gemfiles/rails_5.1.gemfile +14 -0
  31. data/gemfiles/rails_5.2.gemfile +14 -0
  32. data/lib/aasm/aasm.rb +160 -137
  33. data/lib/aasm/base.rb +290 -0
  34. data/lib/aasm/configuration.rb +48 -0
  35. data/lib/aasm/core/event.rb +177 -0
  36. data/lib/aasm/core/invoker.rb +129 -0
  37. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  38. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  39. data/lib/aasm/core/invokers/literal_invoker.rb +47 -0
  40. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  41. data/lib/aasm/core/state.rb +91 -0
  42. data/lib/aasm/core/transition.rb +83 -0
  43. data/lib/aasm/dsl_helper.rb +32 -0
  44. data/lib/aasm/errors.rb +21 -0
  45. data/lib/aasm/instance_base.rb +133 -0
  46. data/lib/aasm/localizer.rb +64 -0
  47. data/lib/aasm/minitest/allow_event.rb +13 -0
  48. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  49. data/lib/aasm/minitest/have_state.rb +13 -0
  50. data/lib/aasm/minitest/transition_from.rb +21 -0
  51. data/lib/aasm/minitest.rb +5 -0
  52. data/lib/aasm/minitest_spec.rb +15 -0
  53. data/lib/aasm/persistence/active_record_persistence.rb +108 -173
  54. data/lib/aasm/persistence/base.rb +89 -0
  55. data/lib/aasm/persistence/core_data_query_persistence.rb +94 -0
  56. data/lib/aasm/persistence/dynamoid_persistence.rb +92 -0
  57. data/lib/aasm/persistence/mongoid_persistence.rb +126 -0
  58. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  59. data/lib/aasm/persistence/orm.rb +154 -0
  60. data/lib/aasm/persistence/plain_persistence.rb +26 -0
  61. data/lib/aasm/persistence/redis_persistence.rb +112 -0
  62. data/lib/aasm/persistence/sequel_persistence.rb +83 -0
  63. data/lib/aasm/persistence.rb +48 -10
  64. data/lib/aasm/rspec/allow_event.rb +26 -0
  65. data/lib/aasm/rspec/allow_transition_to.rb +26 -0
  66. data/lib/aasm/rspec/have_state.rb +22 -0
  67. data/lib/aasm/rspec/transition_from.rb +36 -0
  68. data/lib/aasm/rspec.rb +5 -0
  69. data/lib/aasm/state_machine.rb +40 -22
  70. data/lib/aasm/state_machine_store.rb +76 -0
  71. data/lib/aasm/version.rb +3 -0
  72. data/lib/aasm.rb +21 -1
  73. data/lib/generators/aasm/aasm_generator.rb +16 -0
  74. data/lib/generators/aasm/orm_helpers.rb +41 -0
  75. data/lib/generators/active_record/aasm_generator.rb +40 -0
  76. data/lib/generators/active_record/templates/migration.rb +8 -0
  77. data/lib/generators/active_record/templates/migration_existing.rb +5 -0
  78. data/lib/generators/mongoid/aasm_generator.rb +28 -0
  79. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  80. data/lib/motion-aasm.rb +37 -0
  81. data/spec/database.rb +57 -0
  82. data/spec/database.yml +3 -0
  83. data/spec/en.yml +9 -0
  84. data/spec/generators/active_record_generator_spec.rb +53 -0
  85. data/spec/generators/mongoid_generator_spec.rb +31 -0
  86. data/spec/generators/no_brainer_generator_spec.rb +29 -0
  87. data/spec/localizer_test_model_deprecated_style.yml +13 -0
  88. data/spec/localizer_test_model_new_style.yml +11 -0
  89. data/spec/models/active_record/active_record_callback.rb +93 -0
  90. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  91. data/spec/models/active_record/complex_active_record_example.rb +37 -0
  92. data/spec/models/active_record/derivate_new_dsl.rb +7 -0
  93. data/spec/models/active_record/false_state.rb +35 -0
  94. data/spec/models/active_record/gate.rb +39 -0
  95. data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
  96. data/spec/models/active_record/invalid_persistor.rb +29 -0
  97. data/spec/models/active_record/localizer_test_model.rb +42 -0
  98. data/spec/models/active_record/namespaced.rb +16 -0
  99. data/spec/models/active_record/no_direct_assignment.rb +21 -0
  100. data/spec/models/active_record/no_scope.rb +21 -0
  101. data/spec/models/active_record/persisted_state.rb +12 -0
  102. data/spec/models/active_record/person.rb +23 -0
  103. data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
  104. data/spec/models/active_record/reader.rb +7 -0
  105. data/spec/models/active_record/readme_job.rb +21 -0
  106. data/spec/models/active_record/silent_persistor.rb +29 -0
  107. data/spec/models/active_record/simple_new_dsl.rb +32 -0
  108. data/spec/models/active_record/thief.rb +29 -0
  109. data/spec/models/active_record/timestamp_example.rb +16 -0
  110. data/spec/models/active_record/transactor.rb +124 -0
  111. data/spec/models/active_record/transient.rb +6 -0
  112. data/spec/models/active_record/validator.rb +118 -0
  113. data/spec/models/active_record/with_enum.rb +39 -0
  114. data/spec/models/active_record/with_enum_without_column.rb +38 -0
  115. data/spec/models/active_record/with_false_enum.rb +31 -0
  116. data/spec/models/active_record/with_true_enum.rb +39 -0
  117. data/spec/models/active_record/work.rb +3 -0
  118. data/spec/models/active_record/worker.rb +2 -0
  119. data/spec/models/active_record/writer.rb +6 -0
  120. data/spec/models/basic_two_state_machines_example.rb +25 -0
  121. data/spec/models/callbacks/basic.rb +98 -0
  122. data/spec/models/callbacks/basic_multiple.rb +75 -0
  123. data/spec/models/callbacks/guard_within_block.rb +67 -0
  124. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  125. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +66 -0
  126. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  127. data/spec/models/callbacks/private_method.rb +44 -0
  128. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  129. data/spec/models/callbacks/with_args.rb +62 -0
  130. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  131. data/spec/models/callbacks/with_state_arg.rb +34 -0
  132. data/spec/models/callbacks/with_state_arg_multiple.rb +29 -0
  133. data/spec/models/complex_example.rb +222 -0
  134. data/spec/models/conversation.rb +93 -0
  135. data/spec/models/default_state.rb +12 -0
  136. data/spec/models/double_definer.rb +21 -0
  137. data/spec/models/dynamoid/complex_dynamoid_example.rb +37 -0
  138. data/spec/models/dynamoid/dynamoid_multiple.rb +18 -0
  139. data/spec/models/dynamoid/dynamoid_simple.rb +18 -0
  140. data/spec/models/foo.rb +106 -0
  141. data/spec/models/foo_callback_multiple.rb +45 -0
  142. data/spec/models/guard_arguments_check.rb +17 -0
  143. data/spec/models/guard_with_params.rb +24 -0
  144. data/spec/models/guard_with_params_multiple.rb +18 -0
  145. data/spec/models/guardian.rb +58 -0
  146. data/spec/models/guardian_multiple.rb +48 -0
  147. data/spec/models/guardian_without_from_specified.rb +18 -0
  148. data/spec/models/initial_state_proc.rb +31 -0
  149. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  150. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  151. data/spec/models/mongoid/mongoid_relationships.rb +26 -0
  152. data/spec/models/mongoid/no_scope_mongoid.rb +21 -0
  153. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  154. data/spec/models/mongoid/simple_mongoid.rb +23 -0
  155. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +25 -0
  156. data/spec/models/mongoid/timestamp_example_mongoid.rb +20 -0
  157. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  158. data/spec/models/multi_transitioner.rb +34 -0
  159. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  160. data/spec/models/namespaced_multiple_example.rb +42 -0
  161. data/spec/models/no_initial_state.rb +25 -0
  162. data/spec/models/nobrainer/complex_no_brainer_example.rb +36 -0
  163. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +39 -0
  164. data/spec/models/nobrainer/no_scope_no_brainer.rb +21 -0
  165. data/spec/models/nobrainer/nobrainer_relationships.rb +25 -0
  166. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +39 -0
  167. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +25 -0
  168. data/spec/models/nobrainer/simple_no_brainer.rb +23 -0
  169. data/spec/models/nobrainer/validator_no_brainer.rb +98 -0
  170. data/spec/models/not_auto_loaded/process.rb +21 -0
  171. data/spec/models/parametrised_event.rb +42 -0
  172. data/spec/models/parametrised_event_multiple.rb +29 -0
  173. data/spec/models/process_with_new_dsl.rb +31 -0
  174. data/spec/models/provided_state.rb +24 -0
  175. data/spec/models/redis/complex_redis_example.rb +40 -0
  176. data/spec/models/redis/redis_multiple.rb +20 -0
  177. data/spec/models/redis/redis_simple.rb +20 -0
  178. data/spec/models/sequel/complex_sequel_example.rb +46 -0
  179. data/spec/models/sequel/invalid_persistor.rb +52 -0
  180. data/spec/models/sequel/sequel_multiple.rb +25 -0
  181. data/spec/models/sequel/sequel_simple.rb +26 -0
  182. data/spec/models/sequel/silent_persistor.rb +50 -0
  183. data/spec/models/sequel/transactor.rb +112 -0
  184. data/spec/models/sequel/validator.rb +93 -0
  185. data/spec/models/sequel/worker.rb +12 -0
  186. data/spec/models/silencer.rb +27 -0
  187. data/spec/models/simple_custom_example.rb +53 -0
  188. data/spec/models/simple_example.rb +23 -0
  189. data/spec/models/simple_example_with_guard_args.rb +17 -0
  190. data/spec/models/simple_multiple_example.rb +42 -0
  191. data/spec/models/state_machine_with_failed_event.rb +20 -0
  192. data/spec/models/states_on_one_line_example.rb +8 -0
  193. data/spec/models/sub_class.rb +41 -0
  194. data/spec/models/sub_class_with_more_states.rb +18 -0
  195. data/spec/models/sub_classing.rb +3 -0
  196. data/spec/models/super_class.rb +46 -0
  197. data/spec/models/this_name_better_not_be_in_use.rb +11 -0
  198. data/spec/models/timestamps_example.rb +19 -0
  199. data/spec/models/timestamps_with_named_machine_example.rb +13 -0
  200. data/spec/models/valid_state_name.rb +23 -0
  201. data/spec/spec_helper.rb +41 -0
  202. data/spec/spec_helpers/active_record.rb +8 -0
  203. data/spec/spec_helpers/dynamoid.rb +35 -0
  204. data/spec/spec_helpers/mongoid.rb +26 -0
  205. data/spec/spec_helpers/nobrainer.rb +15 -0
  206. data/spec/spec_helpers/redis.rb +18 -0
  207. data/spec/spec_helpers/remove_warnings.rb +1 -0
  208. data/spec/spec_helpers/sequel.rb +7 -0
  209. data/spec/unit/abstract_class_spec.rb +27 -0
  210. data/spec/unit/api_spec.rb +104 -0
  211. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  212. data/spec/unit/callback_multiple_spec.rb +304 -0
  213. data/spec/unit/callbacks_spec.rb +521 -0
  214. data/spec/unit/complex_example_spec.rb +93 -0
  215. data/spec/unit/complex_multiple_example_spec.rb +115 -0
  216. data/spec/unit/edge_cases_spec.rb +16 -0
  217. data/spec/unit/event_multiple_spec.rb +73 -0
  218. data/spec/unit/event_naming_spec.rb +16 -0
  219. data/spec/unit/event_spec.rb +394 -0
  220. data/spec/unit/exception_spec.rb +11 -0
  221. data/spec/unit/guard_arguments_check_spec.rb +9 -0
  222. data/spec/unit/guard_multiple_spec.rb +60 -0
  223. data/spec/unit/guard_spec.rb +89 -0
  224. data/spec/unit/guard_with_params_multiple_spec.rb +10 -0
  225. data/spec/unit/guard_with_params_spec.rb +14 -0
  226. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  227. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  228. data/spec/unit/initial_state_spec.rb +12 -0
  229. data/spec/unit/inspection_multiple_spec.rb +205 -0
  230. data/spec/unit/inspection_spec.rb +153 -0
  231. data/spec/unit/invoker_spec.rb +189 -0
  232. data/spec/unit/invokers/base_invoker_spec.rb +72 -0
  233. data/spec/unit/invokers/class_invoker_spec.rb +95 -0
  234. data/spec/unit/invokers/literal_invoker_spec.rb +86 -0
  235. data/spec/unit/invokers/proc_invoker_spec.rb +86 -0
  236. data/spec/unit/localizer_spec.rb +109 -0
  237. data/spec/unit/memory_leak_spec.rb +38 -0
  238. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  239. data/spec/unit/namespaced_multiple_example_spec.rb +75 -0
  240. data/spec/unit/new_dsl_spec.rb +12 -0
  241. data/spec/unit/override_warning_spec.rb +94 -0
  242. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +635 -0
  243. data/spec/unit/persistence/active_record_persistence_spec.rb +852 -0
  244. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +135 -0
  245. data/spec/unit/persistence/dynamoid_persistence_spec.rb +84 -0
  246. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +200 -0
  247. data/spec/unit/persistence/mongoid_persistence_spec.rb +177 -0
  248. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +198 -0
  249. data/spec/unit/persistence/no_brainer_persistence_spec.rb +158 -0
  250. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  251. data/spec/unit/persistence/redis_persistence_spec.rb +53 -0
  252. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +148 -0
  253. data/spec/unit/persistence/sequel_persistence_spec.rb +368 -0
  254. data/spec/unit/readme_spec.rb +41 -0
  255. data/spec/unit/reloading_spec.rb +15 -0
  256. data/spec/unit/rspec_matcher_spec.rb +88 -0
  257. data/spec/unit/simple_custom_example_spec.rb +39 -0
  258. data/spec/unit/simple_example_spec.rb +57 -0
  259. data/spec/unit/simple_multiple_example_spec.rb +91 -0
  260. data/spec/unit/state_spec.rb +105 -0
  261. data/spec/unit/states_on_one_line_example_spec.rb +16 -0
  262. data/spec/unit/subclassing_multiple_spec.rb +74 -0
  263. data/spec/unit/subclassing_spec.rb +46 -0
  264. data/spec/unit/timestamps_spec.rb +32 -0
  265. data/spec/unit/transition_spec.rb +436 -0
  266. data/test/minitest_helper.rb +57 -0
  267. data/test/unit/minitest_matcher_test.rb +80 -0
  268. metadata +607 -60
  269. data/CHANGELOG +0 -33
  270. data/README.rdoc +0 -122
  271. data/TODO +0 -9
  272. data/doc/jamis.rb +0 -591
  273. data/lib/aasm/event.rb +0 -76
  274. data/lib/aasm/state.rb +0 -35
  275. data/lib/aasm/state_transition.rb +0 -36
@@ -0,0 +1,26 @@
1
+ RSpec::Matchers.define :allow_transition_to do |state|
2
+ match do |obj|
3
+ @state_machine_name ||= :default
4
+ obj.aasm(@state_machine_name).states({:permitted => true}, *@args).include?(state)
5
+ end
6
+
7
+ chain :on do |state_machine_name|
8
+ @state_machine_name = state_machine_name
9
+ end
10
+
11
+ chain :with do |*args|
12
+ @args = args
13
+ end
14
+
15
+ description do
16
+ "allow transition to #{expected} (on :#{@state_machine_name})"
17
+ end
18
+
19
+ failure_message do |obj|
20
+ "expected that the state :#{expected} would be reachable (on :#{@state_machine_name})"
21
+ end
22
+
23
+ failure_message_when_negated do |obj|
24
+ "expected that the state :#{expected} would not be reachable (on :#{@state_machine_name})"
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ RSpec::Matchers.define :have_state do |state|
2
+ match do |obj|
3
+ @state_machine_name ||= :default
4
+ obj.aasm(@state_machine_name).current_state == state.to_sym
5
+ end
6
+
7
+ chain :on do |state_machine_name|
8
+ @state_machine_name = state_machine_name
9
+ end
10
+
11
+ description do
12
+ "have state #{expected} (on :#{@state_machine_name})"
13
+ end
14
+
15
+ failure_message do |obj|
16
+ "expected that :#{obj.aasm(@state_machine_name).current_state} would be :#{expected} (on :#{@state_machine_name})"
17
+ end
18
+
19
+ failure_message_when_negated do |obj|
20
+ "expected that :#{obj.aasm(@state_machine_name).current_state} would not be :#{expected} (on :#{@state_machine_name})"
21
+ end
22
+ end
@@ -0,0 +1,36 @@
1
+ RSpec::Matchers.define :transition_from do |from_state|
2
+ match do |obj|
3
+ @state_machine_name ||= :default
4
+ obj.aasm(@state_machine_name).current_state = from_state.to_sym
5
+ begin
6
+ obj.send(@event, *@args) && obj.aasm(@state_machine_name).current_state == @to_state.to_sym
7
+ rescue AASM::InvalidTransition
8
+ false
9
+ end
10
+ end
11
+
12
+ chain :on do |state_machine_name|
13
+ @state_machine_name = state_machine_name
14
+ end
15
+
16
+ chain :to do |state|
17
+ @to_state = state
18
+ end
19
+
20
+ chain :on_event do |event, *args|
21
+ @event = event
22
+ @args = args
23
+ end
24
+
25
+ description do
26
+ "transition state to :#{@to_state} from :#{expected} on event :#{@event}, with params: #{@args} (on :#{@state_machine_name})"
27
+ end
28
+
29
+ failure_message do |obj|
30
+ "expected that :#{obj.aasm(@state_machine_name).current_state} would be :#{@to_state} (on :#{@state_machine_name})"
31
+ end
32
+
33
+ failure_message_when_negated do |obj|
34
+ "expected that :#{obj.aasm(@state_machine_name).current_state} would not be :#{@to_state} (on :#{@state_machine_name})"
35
+ end
36
+ end
data/lib/aasm/rspec.rb ADDED
@@ -0,0 +1,5 @@
1
+ # relative-require all rspec files
2
+ Dir[File.dirname(__FILE__) + '/rspec/*.rb'].each do |file|
3
+ require 'aasm/rspec/' + File.basename(file, File.extname(file))
4
+ end
5
+
@@ -1,35 +1,53 @@
1
- require 'ostruct'
2
-
3
1
  module AASM
4
2
  class StateMachine
5
- def self.[](*args)
6
- (@machines ||= {})[args]
7
- end
8
-
9
- def self.[]=(*args)
10
- val = args.pop
11
- (@machines ||= {})[args] = val
12
- end
3
+ # the following four methods provide the storage of all state machines
13
4
 
14
- attr_accessor :states, :events, :initial_state, :config
15
- attr_reader :name
5
+ attr_accessor :states, :events, :initial_state, :config, :name, :global_callbacks
16
6
 
17
7
  def initialize(name)
18
- @name = name
19
8
  @initial_state = nil
20
9
  @states = []
21
10
  @events = {}
22
- @config = OpenStruct.new
11
+ @global_callbacks = {}
12
+ @config = AASM::Configuration.new
13
+ @name = name
23
14
  end
24
15
 
25
- def clone
26
- klone = super
27
- klone.states = states.clone
28
- klone
16
+ # called internally by Ruby 1.9 after clone()
17
+ def initialize_copy(orig)
18
+ super
19
+ @states = orig.states.collect { |state| state.clone }
20
+ @events = {}
21
+ orig.events.each_pair { |name, event| @events[name] = event.clone }
22
+ @global_callbacks = @global_callbacks.dup
29
23
  end
30
24
 
31
- def create_state(name, options)
32
- @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name)
25
+ def add_state(state_name, klass, options)
26
+ set_initial_state(state_name, options)
27
+
28
+ # allow reloading, extending or redefining a state
29
+ @states.delete(state_name) if @states.include?(state_name)
30
+
31
+ @states << AASM::Core::State.new(state_name, klass, self, options)
33
32
  end
34
- end
35
- end
33
+
34
+ def add_event(name, options, &block)
35
+ @events[name] = AASM::Core::Event.new(name, self, options, &block)
36
+ end
37
+
38
+ def add_global_callbacks(name, *callbacks, &block)
39
+ @global_callbacks[name] ||= []
40
+ callbacks.each do |callback|
41
+ @global_callbacks[name] << callback unless @global_callbacks[name].include? callback
42
+ end
43
+ @global_callbacks[name] << block if block
44
+ end
45
+
46
+ private
47
+
48
+ def set_initial_state(name, options)
49
+ @initial_state = name if options[:initial] || !initial_state
50
+ end
51
+
52
+ end # StateMachine
53
+ end # AASM
@@ -0,0 +1,76 @@
1
+ require 'concurrent'
2
+ module AASM
3
+ class StateMachineStore
4
+ @stores = Concurrent::Map.new
5
+
6
+ class << self
7
+ def stores
8
+ @stores
9
+ end
10
+
11
+ # do not overwrite existing state machines, which could have been created by
12
+ # inheritance, see AASM::ClassMethods method inherited
13
+ def register(klass, overwrite = false, state_machine = nil)
14
+ raise "Cannot register #{klass}" unless klass.is_a?(Class)
15
+
16
+ case name = template = overwrite
17
+ when FalseClass then stores[klass.to_s] ||= new
18
+ when TrueClass then stores[klass.to_s] = new
19
+ when Class then stores[klass.to_s] = stores[template.to_s].clone
20
+ when Symbol then stores[klass.to_s].register(name, state_machine)
21
+ when String then stores[klass.to_s].register(name, state_machine)
22
+ else raise "Don't know what to do with #{overwrite}"
23
+ end
24
+ end
25
+ alias_method :[]=, :register
26
+
27
+ def fetch(klass, fallback = nil)
28
+ stores[klass.to_s] || fallback && begin
29
+ match = klass.ancestors.find do |ancestor|
30
+ ancestor.include? AASM and stores[ancestor.to_s]
31
+ end
32
+
33
+ stores[match.to_s]
34
+ end
35
+ end
36
+ alias_method :[], :fetch
37
+
38
+ def unregister(klass)
39
+ stores.delete(klass.to_s)
40
+ end
41
+ end
42
+
43
+ def initialize
44
+ @machines = Concurrent::Map.new
45
+ end
46
+
47
+ def clone
48
+ StateMachineStore.new.tap do |store|
49
+ @machines.each_pair do |name, machine|
50
+ store.register(name, machine.clone)
51
+ end
52
+ end
53
+ end
54
+
55
+ def machine(name)
56
+ @machines[name.to_s]
57
+ end
58
+ alias_method :[], :machine
59
+
60
+ def machine_names
61
+ @machines.keys
62
+ end
63
+ alias_method :keys, :machine_names
64
+
65
+ def register(name, machine, force = false)
66
+ raise "Cannot use #{name.inspect} for machine name" unless name.is_a?(Symbol) or name.is_a?(String)
67
+ raise "Cannot use #{machine.inspect} as a machine" unless machine.is_a?(AASM::StateMachine)
68
+
69
+ if force
70
+ @machines[name.to_s] = machine
71
+ else
72
+ @machines[name.to_s] ||= machine
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module AASM
2
+ VERSION = "5.2.0"
3
+ end
data/lib/aasm.rb CHANGED
@@ -1 +1,21 @@
1
- require File.join(File.dirname(__FILE__), 'aasm', 'aasm')
1
+ require 'aasm/version'
2
+ require 'aasm/errors'
3
+ require 'aasm/configuration'
4
+ require 'aasm/base'
5
+ require 'aasm/dsl_helper'
6
+ require 'aasm/instance_base'
7
+ require 'aasm/core/transition'
8
+ require 'aasm/core/event'
9
+ require 'aasm/core/state'
10
+ require 'aasm/core/invoker'
11
+ require 'aasm/core/invokers/base_invoker'
12
+ require 'aasm/core/invokers/class_invoker'
13
+ require 'aasm/core/invokers/literal_invoker'
14
+ require 'aasm/core/invokers/proc_invoker'
15
+ require 'aasm/localizer'
16
+ require 'aasm/state_machine_store'
17
+ require 'aasm/state_machine'
18
+ require 'aasm/persistence'
19
+ require 'aasm/persistence/base'
20
+ require 'aasm/persistence/plain_persistence'
21
+ require 'aasm/aasm'
@@ -0,0 +1,16 @@
1
+ require 'rails/generators/named_base'
2
+
3
+ module AASM
4
+ module Generators
5
+ class AASMGenerator < Rails::Generators::NamedBase
6
+ namespace "aasm"
7
+ argument :column_name, type: :string, default: 'aasm_state'
8
+
9
+ desc "Generates a model with the given NAME (if one does not exist) with aasm " <<
10
+ "block and migration to add aasm_state column."
11
+
12
+ hook_for :orm
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ module AASM
2
+ module Generators
3
+ module OrmHelpers
4
+
5
+ def model_contents
6
+ if column_name == 'aasm_state'
7
+ <<RUBY
8
+ include AASM
9
+
10
+ aasm do
11
+ end
12
+ RUBY
13
+ else
14
+ <<RUBY
15
+ include AASM
16
+
17
+ aasm :column => '#{column_name}' do
18
+ end
19
+ RUBY
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def column_exists?
26
+ table_name.singularize.humanize.constantize.column_names.include?(column_name.to_s)
27
+ rescue NameError
28
+ false
29
+ end
30
+
31
+ def model_exists?
32
+ File.exists?(File.join(destination_root, model_path))
33
+ end
34
+
35
+ def model_path
36
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ require 'rails/generators/active_record'
2
+ require 'generators/aasm/orm_helpers'
3
+
4
+ module ActiveRecord
5
+ module Generators
6
+ class AASMGenerator < ActiveRecord::Generators::Base
7
+ include AASM::Generators::OrmHelpers
8
+ namespace "active_record:aasm"
9
+ argument :column_name, type: :string, default: 'aasm_state'
10
+
11
+ source_root File.expand_path("../templates", __FILE__)
12
+
13
+ def copy_aasm_migration
14
+ if column_exists?
15
+ puts "Both model and column exists"
16
+ elsif model_exists?
17
+ migration_template "migration_existing.rb", "db/migrate/add_#{column_name}_to_#{table_name}.rb"
18
+ else
19
+ migration_template "migration.rb", "db/migrate/aasm_create_#{table_name}.rb"
20
+ end
21
+ end
22
+
23
+ def generate_model
24
+ invoke "active_record:model", [name], migration: false unless model_exists?
25
+ end
26
+
27
+ def inject_aasm_content
28
+ content = model_contents
29
+
30
+ class_path = if namespaced?
31
+ class_name.to_s.split("::")
32
+ else
33
+ [class_name]
34
+ end
35
+ inject_into_class(model_path, class_path.last, content) if model_exists?
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,8 @@
1
+ class AASMCreate<%= table_name.camelize %> < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ create_table(:<%= table_name %>) do |t|
4
+ t.string :<%= column_name %>
5
+ t.timestamps null: false
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class Add<%= column_name.camelize %>To<%= table_name.camelize %> < ActiveRecord::Migration[<%= ActiveRecord::VERSION::STRING.to_f %>]
2
+ def change
3
+ add_column :<%= table_name %>, :<%= column_name %>, :string
4
+ end
5
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails/generators/named_base'
2
+ require 'generators/aasm/orm_helpers'
3
+
4
+ module Mongoid
5
+ module Generators
6
+ class AASMGenerator < Rails::Generators::NamedBase
7
+ include AASM::Generators::OrmHelpers
8
+ namespace "mongoid:aasm"
9
+ argument :column_name, type: :string, default: 'aasm_state'
10
+
11
+ def generate_model
12
+ invoke "mongoid:model", [name] unless model_exists?
13
+ end
14
+
15
+ def inject_aasm_content
16
+ inject_into_file model_path, model_contents, after: "include Mongoid::Document\n" if model_exists?
17
+ end
18
+
19
+ def inject_field_types
20
+ inject_into_file model_path, migration_data, after: "include Mongoid::Document\n" if model_exists?
21
+ end
22
+
23
+ def migration_data
24
+ " field :#{column_name}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require 'rails/generators/named_base'
2
+ require 'generators/aasm/orm_helpers'
3
+
4
+ module NoBrainer
5
+ module Generators
6
+ class AASMGenerator < Rails::Generators::NamedBase
7
+ include AASM::Generators::OrmHelpers
8
+ namespace 'nobrainer:aasm'
9
+ argument :column_name, type: :string, default: 'aasm_state'
10
+
11
+ def generate_model
12
+ invoke 'nobrainer:model', [name] unless model_exists?
13
+ end
14
+
15
+ def inject_aasm_content
16
+ inject_into_file model_path, model_contents, after: "include NoBrainer::Document::Timestamps\n" if model_exists?
17
+ end
18
+
19
+ def inject_field_types
20
+ inject_into_file model_path, migration_data, after: "include NoBrainer::Document::Timestamps\n" if model_exists?
21
+ end
22
+
23
+ def migration_data
24
+ " field :#{column_name}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,37 @@
1
+ unless defined?(Motion::Project::App)
2
+ raise "This must be required from within a RubyMotion Rakefile"
3
+ end
4
+
5
+ file_dependencies = {
6
+ 'aasm/aasm.rb' => ['aasm/persistence.rb'],
7
+ 'aasm/persistence.rb' => ['aasm/persistence/plain_persistence.rb', 'aasm/persistence/core_data_query_persistence.rb'],
8
+ 'aasm/persistence/base.rb' => ['aasm/base.rb'],
9
+ 'aasm/persistence/core_data_query_persistence.rb' => ['aasm/persistence/base.rb']
10
+ }
11
+
12
+ exclude_files = [
13
+ 'aasm/rspec.*',
14
+ 'aasm/minitest.*',
15
+ 'aasm/minitest_spec.*',
16
+ 'aasm/persistence/active_record_persistence.rb',
17
+ 'aasm/persistence/dynamoid_persistence.rb',
18
+ 'aasm/persistence/mongoid_persistence.rb',
19
+ 'aasm/persistence/no_brainer_persistence.rb',
20
+ 'aasm/persistence/sequel_persistence.rb',
21
+ 'aasm/persistence/redis_persistence.rb'
22
+ ]
23
+
24
+ Motion::Project::App.setup do |app|
25
+ parent = File.expand_path File.dirname(__FILE__)
26
+
27
+ app.files.unshift Dir.glob(File.join(parent, "aasm/**/*.rb")).reject { |file| exclude_files.any? { |exclude| file.match(exclude) } }
28
+
29
+ app.files_dependencies file_dependencies.inject({}, &->(file_dependencies, (file, *dependencies)) do
30
+ file = File.join(parent, file)
31
+ dependencies = dependencies.flatten(1).map do |dependency|
32
+ File.join(parent, dependency)
33
+ end
34
+
35
+ file_dependencies.merge({ file => dependencies })
36
+ end)
37
+ end
data/spec/database.rb ADDED
@@ -0,0 +1,57 @@
1
+ ActiveRecord::Migration.suppress_messages do
2
+ %w{gates multiple_gates readers writers transients simples no_scopes multiple_no_scopes no_direct_assignments multiple_no_direct_assignments thieves multiple_thieves localizer_test_models persisted_states provided_and_persisted_states with_enums with_enum_without_columns multiple_with_enum_without_columns with_true_enums with_false_enums false_states multiple_with_enums multiple_with_true_enums multiple_with_false_enums multiple_false_states readme_jobs}.each do |table_name|
3
+ ActiveRecord::Migration.create_table table_name, :force => true do |t|
4
+ t.string "aasm_state"
5
+ end
6
+ end
7
+
8
+ %w(simple_new_dsls multiple_simple_new_dsls implemented_abstract_class_dsls users multiple_namespaceds).each do |table_name|
9
+ ActiveRecord::Migration.create_table table_name, :force => true do |t|
10
+ t.string "status"
11
+ end
12
+ end
13
+
14
+ ActiveRecord::Migration.create_table "complex_active_record_examples", :force => true do |t|
15
+ t.string "left"
16
+ t.string "right"
17
+ end
18
+
19
+ ActiveRecord::Migration.create_table "works", :force => true do |t|
20
+ t.string "status"
21
+ end
22
+
23
+ %w(validators multiple_validators workers invalid_persistors multiple_invalid_persistors silent_persistors multiple_silent_persistors active_record_callbacks).each do |table_name|
24
+ ActiveRecord::Migration.create_table table_name, :force => true do |t|
25
+ t.string "name"
26
+ t.string "status"
27
+ end
28
+ end
29
+
30
+ %w(transactors no_lock_transactors lock_transactors lock_no_wait_transactors no_transactors multiple_transactors).each do |table_name|
31
+ ActiveRecord::Migration.create_table table_name, :force => true do |t|
32
+ t.string "name"
33
+ t.string "status"
34
+ t.integer "worker_id"
35
+ end
36
+ end
37
+
38
+ ActiveRecord::Migration.create_table "fathers", :force => true do |t|
39
+ t.string "aasm_state"
40
+ t.string "type"
41
+ end
42
+
43
+ ActiveRecord::Migration.create_table "basic_active_record_two_state_machines_examples", :force => true do |t|
44
+ t.string "search"
45
+ t.string "sync"
46
+ end
47
+
48
+ ActiveRecord::Migration.create_table "instance_level_skip_validation_examples", :force => true do |t|
49
+ t.string "state"
50
+ t.string "some_string"
51
+ end
52
+
53
+ ActiveRecord::Migration.create_table "timestamp_examples", :force => true do |t|
54
+ t.string "aasm_state"
55
+ t.datetime "opened_at"
56
+ end
57
+ end
data/spec/database.yml ADDED
@@ -0,0 +1,3 @@
1
+ sqlite3:
2
+ adapter: sqlite3
3
+ database: spec/aasm.sqlite3.db
data/spec/en.yml ADDED
@@ -0,0 +1,9 @@
1
+ en:
2
+ activerecord:
3
+ events:
4
+ localizer_test_model:
5
+ close: "Let's close it!"
6
+
7
+ errors:
8
+ messages:
9
+ record_invalid: "Invalid record"
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ if defined?(ActiveRecord)
4
+ require 'generator_spec'
5
+ require 'generators/active_record/aasm_generator'
6
+
7
+ describe ActiveRecord::Generators::AASMGenerator, type: :generator do
8
+ destination File.expand_path("../../../tmp", __FILE__)
9
+
10
+ before(:all) do
11
+ prepare_destination
12
+ end
13
+
14
+ it "creates model with aasm block for default column_name" do
15
+ run_generator %w(user)
16
+ assert_file "app/models/user.rb", /include AASM\n\n aasm do\n end\n/
17
+ end
18
+
19
+ it "creates model with aasm block for custom column_name" do
20
+ run_generator %w(user state)
21
+ assert_file "app/models/user.rb", /aasm :column => 'state' do\n end\n/
22
+ end
23
+
24
+ it "creates model with aasm block for namespaced model" do
25
+ run_generator %w(Admin::User state)
26
+ assert_file "app/models/admin/user.rb", /aasm :column => 'state' do\n end\n/
27
+ end
28
+
29
+ it "creates migration for model with aasm_column" do
30
+ run_generator %w(post)
31
+ assert_migration "db/migrate/aasm_create_posts.rb", /create_table(:posts) do |t|\n t.string :aasm_state\n/
32
+ end
33
+
34
+ it "add aasm_column in existing model" do
35
+ run_generator %w(job)
36
+ assert_file "app/models/job.rb"
37
+ run_generator %w(job)
38
+ assert_migration "db/migrate/add_aasm_state_to_jobs.rb"
39
+ end
40
+
41
+ it "add custom aasm_column in existing model" do
42
+ run_generator %w(job state)
43
+ assert_migration "db/migrate/add_state_to_jobs.rb"
44
+ end
45
+
46
+ it "dont add column if column is already exists" do
47
+ require 'models/active_record/work.rb'
48
+ load_schema
49
+ run_generator %w(work status)
50
+ assert_no_migration "db/migrate/add_status_to_jobs.rb"
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ if defined?(Mongoid::Document)
4
+ require 'generator_spec'
5
+ require 'generators/mongoid/aasm_generator'
6
+
7
+ describe Mongoid::Generators::AASMGenerator, type: :generator do
8
+ destination File.expand_path("../../../tmp", __FILE__)
9
+
10
+ before(:all) do
11
+ prepare_destination
12
+ end
13
+
14
+ it "creates model with aasm block for default column_name" do
15
+ run_generator %w(user)
16
+ assert_file "app/models/user.rb", /include AASM\n\n aasm do\n end\n/
17
+ end
18
+
19
+ it "creates model with aasm block for custom column_name" do
20
+ run_generator %w(user state)
21
+ assert_file "app/models/user.rb", /aasm :column => 'state' do\n end\n/
22
+ end
23
+
24
+ it "creates model with aasm block for namespaced model" do
25
+ run_generator %w(Admin::User state)
26
+ assert_file "app/models/admin/user.rb", /aasm :column => 'state' do\n end\n/
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ if defined?(NoBrainer::Document)
4
+ require 'generator_spec'
5
+ require 'generators/nobrainer/aasm_generator'
6
+
7
+ describe NoBrainer::Generators::AASMGenerator, type: :generator do
8
+ destination File.expand_path('../../../tmp', __FILE__)
9
+
10
+ before(:all) do
11
+ prepare_destination
12
+ end
13
+
14
+ it 'creates model with aasm block for default column_name' do
15
+ run_generator %w[user]
16
+ assert_file 'app/models/user.rb', /include AASM\n\n aasm do\n end\n/
17
+ end
18
+
19
+ it 'creates model with aasm block for custom column_name' do
20
+ run_generator %w[user state]
21
+ assert_file 'app/models/user.rb', /aasm :column => 'state' do\n end\n/
22
+ end
23
+
24
+ it 'creates model with aasm block for namespaced model' do
25
+ run_generator %w[Admin::User state]
26
+ assert_file 'app/models/admin/user.rb', /aasm :column => 'state' do\n end\n/
27
+ end
28
+ end
29
+ end