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.
- checksums.yaml +7 -0
- data/.document +6 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +20 -0
- data/.travis.yml +82 -0
- data/API +34 -0
- data/Appraisals +67 -0
- data/CHANGELOG.md +453 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/CONTRIBUTING.md +24 -0
- data/Dockerfile +44 -0
- data/Gemfile +6 -0
- data/Gemfile.lock_old +151 -0
- data/HOWTO +12 -0
- data/{MIT-LICENSE → LICENSE} +1 -1
- data/PLANNED_CHANGES.md +11 -0
- data/README.md +1524 -0
- data/README_FROM_VERSION_3_TO_4.md +240 -0
- data/Rakefile +20 -84
- data/TESTING.md +25 -0
- data/aasm.gemspec +37 -0
- data/docker-compose.yml +40 -0
- data/gemfiles/norails.gemfile +10 -0
- data/gemfiles/rails_4.2.gemfile +17 -0
- data/gemfiles/rails_4.2_mongoid_5.gemfile +12 -0
- data/gemfiles/rails_4.2_nobrainer.gemfile +9 -0
- data/gemfiles/rails_5.0.gemfile +14 -0
- data/gemfiles/rails_5.0_nobrainer.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +14 -0
- data/gemfiles/rails_5.2.gemfile +14 -0
- data/lib/aasm/aasm.rb +160 -137
- data/lib/aasm/base.rb +290 -0
- data/lib/aasm/configuration.rb +48 -0
- data/lib/aasm/core/event.rb +177 -0
- data/lib/aasm/core/invoker.rb +129 -0
- data/lib/aasm/core/invokers/base_invoker.rb +75 -0
- data/lib/aasm/core/invokers/class_invoker.rb +52 -0
- data/lib/aasm/core/invokers/literal_invoker.rb +47 -0
- data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
- data/lib/aasm/core/state.rb +91 -0
- data/lib/aasm/core/transition.rb +83 -0
- data/lib/aasm/dsl_helper.rb +32 -0
- data/lib/aasm/errors.rb +21 -0
- data/lib/aasm/instance_base.rb +133 -0
- data/lib/aasm/localizer.rb +64 -0
- data/lib/aasm/minitest/allow_event.rb +13 -0
- data/lib/aasm/minitest/allow_transition_to.rb +13 -0
- data/lib/aasm/minitest/have_state.rb +13 -0
- data/lib/aasm/minitest/transition_from.rb +21 -0
- data/lib/aasm/minitest.rb +5 -0
- data/lib/aasm/minitest_spec.rb +15 -0
- data/lib/aasm/persistence/active_record_persistence.rb +108 -173
- data/lib/aasm/persistence/base.rb +89 -0
- data/lib/aasm/persistence/core_data_query_persistence.rb +94 -0
- data/lib/aasm/persistence/dynamoid_persistence.rb +92 -0
- data/lib/aasm/persistence/mongoid_persistence.rb +126 -0
- data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
- data/lib/aasm/persistence/orm.rb +154 -0
- data/lib/aasm/persistence/plain_persistence.rb +26 -0
- data/lib/aasm/persistence/redis_persistence.rb +112 -0
- data/lib/aasm/persistence/sequel_persistence.rb +83 -0
- data/lib/aasm/persistence.rb +48 -10
- data/lib/aasm/rspec/allow_event.rb +26 -0
- data/lib/aasm/rspec/allow_transition_to.rb +26 -0
- data/lib/aasm/rspec/have_state.rb +22 -0
- data/lib/aasm/rspec/transition_from.rb +36 -0
- data/lib/aasm/rspec.rb +5 -0
- data/lib/aasm/state_machine.rb +40 -22
- data/lib/aasm/state_machine_store.rb +76 -0
- data/lib/aasm/version.rb +3 -0
- data/lib/aasm.rb +21 -1
- data/lib/generators/aasm/aasm_generator.rb +16 -0
- data/lib/generators/aasm/orm_helpers.rb +41 -0
- data/lib/generators/active_record/aasm_generator.rb +40 -0
- data/lib/generators/active_record/templates/migration.rb +8 -0
- data/lib/generators/active_record/templates/migration_existing.rb +5 -0
- data/lib/generators/mongoid/aasm_generator.rb +28 -0
- data/lib/generators/nobrainer/aasm_generator.rb +28 -0
- data/lib/motion-aasm.rb +37 -0
- data/spec/database.rb +57 -0
- data/spec/database.yml +3 -0
- data/spec/en.yml +9 -0
- data/spec/generators/active_record_generator_spec.rb +53 -0
- data/spec/generators/mongoid_generator_spec.rb +31 -0
- data/spec/generators/no_brainer_generator_spec.rb +29 -0
- data/spec/localizer_test_model_deprecated_style.yml +13 -0
- data/spec/localizer_test_model_new_style.yml +11 -0
- data/spec/models/active_record/active_record_callback.rb +93 -0
- data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
- data/spec/models/active_record/complex_active_record_example.rb +37 -0
- data/spec/models/active_record/derivate_new_dsl.rb +7 -0
- data/spec/models/active_record/false_state.rb +35 -0
- data/spec/models/active_record/gate.rb +39 -0
- data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
- data/spec/models/active_record/invalid_persistor.rb +29 -0
- data/spec/models/active_record/localizer_test_model.rb +42 -0
- data/spec/models/active_record/namespaced.rb +16 -0
- data/spec/models/active_record/no_direct_assignment.rb +21 -0
- data/spec/models/active_record/no_scope.rb +21 -0
- data/spec/models/active_record/persisted_state.rb +12 -0
- data/spec/models/active_record/person.rb +23 -0
- data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
- data/spec/models/active_record/reader.rb +7 -0
- data/spec/models/active_record/readme_job.rb +21 -0
- data/spec/models/active_record/silent_persistor.rb +29 -0
- data/spec/models/active_record/simple_new_dsl.rb +32 -0
- data/spec/models/active_record/thief.rb +29 -0
- data/spec/models/active_record/timestamp_example.rb +16 -0
- data/spec/models/active_record/transactor.rb +124 -0
- data/spec/models/active_record/transient.rb +6 -0
- data/spec/models/active_record/validator.rb +118 -0
- data/spec/models/active_record/with_enum.rb +39 -0
- data/spec/models/active_record/with_enum_without_column.rb +38 -0
- data/spec/models/active_record/with_false_enum.rb +31 -0
- data/spec/models/active_record/with_true_enum.rb +39 -0
- data/spec/models/active_record/work.rb +3 -0
- data/spec/models/active_record/worker.rb +2 -0
- data/spec/models/active_record/writer.rb +6 -0
- data/spec/models/basic_two_state_machines_example.rb +25 -0
- data/spec/models/callbacks/basic.rb +98 -0
- data/spec/models/callbacks/basic_multiple.rb +75 -0
- data/spec/models/callbacks/guard_within_block.rb +67 -0
- data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
- data/spec/models/callbacks/multiple_transitions_transition_guard.rb +66 -0
- data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
- data/spec/models/callbacks/private_method.rb +44 -0
- data/spec/models/callbacks/private_method_multiple.rb +44 -0
- data/spec/models/callbacks/with_args.rb +62 -0
- data/spec/models/callbacks/with_args_multiple.rb +61 -0
- data/spec/models/callbacks/with_state_arg.rb +34 -0
- data/spec/models/callbacks/with_state_arg_multiple.rb +29 -0
- data/spec/models/complex_example.rb +222 -0
- data/spec/models/conversation.rb +93 -0
- data/spec/models/default_state.rb +12 -0
- data/spec/models/double_definer.rb +21 -0
- data/spec/models/dynamoid/complex_dynamoid_example.rb +37 -0
- data/spec/models/dynamoid/dynamoid_multiple.rb +18 -0
- data/spec/models/dynamoid/dynamoid_simple.rb +18 -0
- data/spec/models/foo.rb +106 -0
- data/spec/models/foo_callback_multiple.rb +45 -0
- data/spec/models/guard_arguments_check.rb +17 -0
- data/spec/models/guard_with_params.rb +24 -0
- data/spec/models/guard_with_params_multiple.rb +18 -0
- data/spec/models/guardian.rb +58 -0
- data/spec/models/guardian_multiple.rb +48 -0
- data/spec/models/guardian_without_from_specified.rb +18 -0
- data/spec/models/initial_state_proc.rb +31 -0
- data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
- data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
- data/spec/models/mongoid/mongoid_relationships.rb +26 -0
- data/spec/models/mongoid/no_scope_mongoid.rb +21 -0
- data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
- data/spec/models/mongoid/simple_mongoid.rb +23 -0
- data/spec/models/mongoid/simple_new_dsl_mongoid.rb +25 -0
- data/spec/models/mongoid/timestamp_example_mongoid.rb +20 -0
- data/spec/models/mongoid/validator_mongoid.rb +100 -0
- data/spec/models/multi_transitioner.rb +34 -0
- data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
- data/spec/models/namespaced_multiple_example.rb +42 -0
- data/spec/models/no_initial_state.rb +25 -0
- data/spec/models/nobrainer/complex_no_brainer_example.rb +36 -0
- data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +39 -0
- data/spec/models/nobrainer/no_scope_no_brainer.rb +21 -0
- data/spec/models/nobrainer/nobrainer_relationships.rb +25 -0
- data/spec/models/nobrainer/silent_persistor_no_brainer.rb +39 -0
- data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +25 -0
- data/spec/models/nobrainer/simple_no_brainer.rb +23 -0
- data/spec/models/nobrainer/validator_no_brainer.rb +98 -0
- data/spec/models/not_auto_loaded/process.rb +21 -0
- data/spec/models/parametrised_event.rb +42 -0
- data/spec/models/parametrised_event_multiple.rb +29 -0
- data/spec/models/process_with_new_dsl.rb +31 -0
- data/spec/models/provided_state.rb +24 -0
- data/spec/models/redis/complex_redis_example.rb +40 -0
- data/spec/models/redis/redis_multiple.rb +20 -0
- data/spec/models/redis/redis_simple.rb +20 -0
- data/spec/models/sequel/complex_sequel_example.rb +46 -0
- data/spec/models/sequel/invalid_persistor.rb +52 -0
- data/spec/models/sequel/sequel_multiple.rb +25 -0
- data/spec/models/sequel/sequel_simple.rb +26 -0
- data/spec/models/sequel/silent_persistor.rb +50 -0
- data/spec/models/sequel/transactor.rb +112 -0
- data/spec/models/sequel/validator.rb +93 -0
- data/spec/models/sequel/worker.rb +12 -0
- data/spec/models/silencer.rb +27 -0
- data/spec/models/simple_custom_example.rb +53 -0
- data/spec/models/simple_example.rb +23 -0
- data/spec/models/simple_example_with_guard_args.rb +17 -0
- data/spec/models/simple_multiple_example.rb +42 -0
- data/spec/models/state_machine_with_failed_event.rb +20 -0
- data/spec/models/states_on_one_line_example.rb +8 -0
- data/spec/models/sub_class.rb +41 -0
- data/spec/models/sub_class_with_more_states.rb +18 -0
- data/spec/models/sub_classing.rb +3 -0
- data/spec/models/super_class.rb +46 -0
- data/spec/models/this_name_better_not_be_in_use.rb +11 -0
- data/spec/models/timestamps_example.rb +19 -0
- data/spec/models/timestamps_with_named_machine_example.rb +13 -0
- data/spec/models/valid_state_name.rb +23 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/spec_helpers/active_record.rb +8 -0
- data/spec/spec_helpers/dynamoid.rb +35 -0
- data/spec/spec_helpers/mongoid.rb +26 -0
- data/spec/spec_helpers/nobrainer.rb +15 -0
- data/spec/spec_helpers/redis.rb +18 -0
- data/spec/spec_helpers/remove_warnings.rb +1 -0
- data/spec/spec_helpers/sequel.rb +7 -0
- data/spec/unit/abstract_class_spec.rb +27 -0
- data/spec/unit/api_spec.rb +104 -0
- data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
- data/spec/unit/callback_multiple_spec.rb +304 -0
- data/spec/unit/callbacks_spec.rb +521 -0
- data/spec/unit/complex_example_spec.rb +93 -0
- data/spec/unit/complex_multiple_example_spec.rb +115 -0
- data/spec/unit/edge_cases_spec.rb +16 -0
- data/spec/unit/event_multiple_spec.rb +73 -0
- data/spec/unit/event_naming_spec.rb +16 -0
- data/spec/unit/event_spec.rb +394 -0
- data/spec/unit/exception_spec.rb +11 -0
- data/spec/unit/guard_arguments_check_spec.rb +9 -0
- data/spec/unit/guard_multiple_spec.rb +60 -0
- data/spec/unit/guard_spec.rb +89 -0
- data/spec/unit/guard_with_params_multiple_spec.rb +10 -0
- data/spec/unit/guard_with_params_spec.rb +14 -0
- data/spec/unit/guard_without_from_specified_spec.rb +10 -0
- data/spec/unit/initial_state_multiple_spec.rb +15 -0
- data/spec/unit/initial_state_spec.rb +12 -0
- data/spec/unit/inspection_multiple_spec.rb +205 -0
- data/spec/unit/inspection_spec.rb +153 -0
- data/spec/unit/invoker_spec.rb +189 -0
- data/spec/unit/invokers/base_invoker_spec.rb +72 -0
- data/spec/unit/invokers/class_invoker_spec.rb +95 -0
- data/spec/unit/invokers/literal_invoker_spec.rb +86 -0
- data/spec/unit/invokers/proc_invoker_spec.rb +86 -0
- data/spec/unit/localizer_spec.rb +109 -0
- data/spec/unit/memory_leak_spec.rb +38 -0
- data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
- data/spec/unit/namespaced_multiple_example_spec.rb +75 -0
- data/spec/unit/new_dsl_spec.rb +12 -0
- data/spec/unit/override_warning_spec.rb +94 -0
- data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +635 -0
- data/spec/unit/persistence/active_record_persistence_spec.rb +852 -0
- data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +135 -0
- data/spec/unit/persistence/dynamoid_persistence_spec.rb +84 -0
- data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +200 -0
- data/spec/unit/persistence/mongoid_persistence_spec.rb +177 -0
- data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +198 -0
- data/spec/unit/persistence/no_brainer_persistence_spec.rb +158 -0
- data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
- data/spec/unit/persistence/redis_persistence_spec.rb +53 -0
- data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +148 -0
- data/spec/unit/persistence/sequel_persistence_spec.rb +368 -0
- data/spec/unit/readme_spec.rb +41 -0
- data/spec/unit/reloading_spec.rb +15 -0
- data/spec/unit/rspec_matcher_spec.rb +88 -0
- data/spec/unit/simple_custom_example_spec.rb +39 -0
- data/spec/unit/simple_example_spec.rb +57 -0
- data/spec/unit/simple_multiple_example_spec.rb +91 -0
- data/spec/unit/state_spec.rb +105 -0
- data/spec/unit/states_on_one_line_example_spec.rb +16 -0
- data/spec/unit/subclassing_multiple_spec.rb +74 -0
- data/spec/unit/subclassing_spec.rb +46 -0
- data/spec/unit/timestamps_spec.rb +32 -0
- data/spec/unit/transition_spec.rb +436 -0
- data/test/minitest_helper.rb +57 -0
- data/test/unit/minitest_matcher_test.rb +80 -0
- metadata +607 -60
- data/CHANGELOG +0 -33
- data/README.rdoc +0 -122
- data/TODO +0 -9
- data/doc/jamis.rb +0 -591
- data/lib/aasm/event.rb +0 -76
- data/lib/aasm/state.rb +0 -35
- data/lib/aasm/state_transition.rb +0 -36
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'aasm/persistence/orm'
|
|
1
2
|
module AASM
|
|
2
3
|
module Persistence
|
|
3
4
|
module ActiveRecordPersistence
|
|
@@ -6,14 +7,9 @@ module AASM
|
|
|
6
7
|
# * extends the model with ClassMethods
|
|
7
8
|
# * includes InstanceMethods
|
|
8
9
|
#
|
|
9
|
-
# Unless the corresponding methods are already defined, it includes
|
|
10
|
-
# * ReadState
|
|
11
|
-
# * WriteState
|
|
12
|
-
# * WriteStateWithoutPersistence
|
|
13
|
-
#
|
|
14
10
|
# Adds
|
|
15
11
|
#
|
|
16
|
-
#
|
|
12
|
+
# after_initialize :aasm_ensure_initial_state
|
|
17
13
|
#
|
|
18
14
|
# As a result, it doesn't matter when you define your methods - the following 2 are equivalent
|
|
19
15
|
#
|
|
@@ -32,119 +28,116 @@ module AASM
|
|
|
32
28
|
# end
|
|
33
29
|
#
|
|
34
30
|
def self.included(base)
|
|
35
|
-
base.
|
|
31
|
+
base.send(:include, AASM::Persistence::Base)
|
|
32
|
+
base.send(:include, AASM::Persistence::ORM)
|
|
36
33
|
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
|
|
37
|
-
base.
|
|
38
|
-
base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteState) unless base.method_defined?(:aasm_write_state)
|
|
39
|
-
base.send(:include, AASM::Persistence::ActiveRecordPersistence::WriteStateWithoutPersistence) unless base.method_defined?(:aasm_write_state_without_persistence)
|
|
40
|
-
|
|
41
|
-
if base.respond_to?(:named_scope)
|
|
42
|
-
base.extend(AASM::Persistence::ActiveRecordPersistence::NamedScopeMethods)
|
|
43
|
-
|
|
44
|
-
base.class_eval do
|
|
45
|
-
class << self
|
|
46
|
-
unless method_defined?(:aasm_state_without_named_scope)
|
|
47
|
-
alias_method :aasm_state_without_named_scope, :aasm_state
|
|
48
|
-
alias_method :aasm_state, :aasm_state_with_named_scope
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
34
|
+
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods
|
|
53
35
|
|
|
54
|
-
base.
|
|
36
|
+
base.after_initialize :aasm_ensure_initial_state
|
|
37
|
+
|
|
38
|
+
# ensure state is in the list of states
|
|
39
|
+
base.validate :aasm_validate_states
|
|
55
40
|
end
|
|
56
41
|
|
|
57
42
|
module ClassMethods
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
#
|
|
65
|
-
# class Foo < ActiveRecord::Base
|
|
66
|
-
# include AASM
|
|
67
|
-
# end
|
|
68
|
-
#
|
|
69
|
-
# OR:
|
|
70
|
-
#
|
|
71
|
-
# create_table :foos do |t|
|
|
72
|
-
# t.string :name
|
|
73
|
-
# t.string :status
|
|
74
|
-
# end
|
|
75
|
-
#
|
|
76
|
-
# class Foo < ActiveRecord::Base
|
|
77
|
-
# include AASM
|
|
78
|
-
# aasm_column :status
|
|
79
|
-
# end
|
|
80
|
-
#
|
|
81
|
-
# This method is both a getter and a setter
|
|
82
|
-
def aasm_column(column_name=nil)
|
|
83
|
-
if column_name
|
|
84
|
-
AASM::StateMachine[self].config.column = column_name.to_sym
|
|
85
|
-
# @aasm_column = column_name.to_sym
|
|
43
|
+
def aasm_create_scope(state_machine_name, scope_name)
|
|
44
|
+
if ActiveRecord::VERSION::MAJOR >= 3
|
|
45
|
+
conditions = { aasm(state_machine_name).attribute_name => scope_name.to_s }
|
|
46
|
+
class_eval do
|
|
47
|
+
scope scope_name, lambda { where(table_name => conditions) }
|
|
48
|
+
end
|
|
86
49
|
else
|
|
87
|
-
|
|
88
|
-
|
|
50
|
+
conditions = {
|
|
51
|
+
table_name => { aasm(state_machine_name).attribute_name => scope_name.to_s }
|
|
52
|
+
}
|
|
53
|
+
class_eval do
|
|
54
|
+
named_scope scope_name, :conditions => conditions
|
|
55
|
+
end
|
|
89
56
|
end
|
|
90
|
-
# @aasm_column
|
|
91
|
-
AASM::StateMachine[self].config.column
|
|
92
57
|
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
module InstanceMethods
|
|
61
|
+
|
|
62
|
+
private
|
|
93
63
|
|
|
94
|
-
def
|
|
95
|
-
|
|
96
|
-
|
|
64
|
+
def aasm_execute_after_commit
|
|
65
|
+
begin
|
|
66
|
+
require 'after_commit_everywhere'
|
|
67
|
+
raise LoadError unless Gem::Version.new(::AfterCommitEverywhere::VERSION) >= Gem::Version.new('0.1.5')
|
|
68
|
+
|
|
69
|
+
self.extend ::AfterCommitEverywhere
|
|
70
|
+
after_commit do
|
|
71
|
+
yield
|
|
72
|
+
end
|
|
73
|
+
rescue LoadError
|
|
74
|
+
warn <<-MSG
|
|
75
|
+
[DEPRECATION] :after_commit AASM callback is not safe in terms of race conditions and redundant calls.
|
|
76
|
+
Please add `gem 'after_commit_everywhere', '~> 1.0'` to your Gemfile in order to fix that.
|
|
77
|
+
MSG
|
|
78
|
+
yield
|
|
97
79
|
end
|
|
98
80
|
end
|
|
99
81
|
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
82
|
+
def aasm_raise_invalid_record
|
|
83
|
+
raise ActiveRecord::RecordInvalid.new(self)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def aasm_save
|
|
87
|
+
self.save
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def aasm_update_column(attribute_name, value)
|
|
91
|
+
self.class.unscoped.where(self.class.primary_key => self.id).update_all(attribute_name => value) == 1
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def aasm_read_attribute(name)
|
|
95
|
+
read_attribute(name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def aasm_write_attribute(name, value)
|
|
99
|
+
write_attribute(name, value)
|
|
104
100
|
end
|
|
105
101
|
|
|
106
|
-
def
|
|
107
|
-
|
|
108
|
-
|
|
102
|
+
def aasm_transaction(requires_new, requires_lock)
|
|
103
|
+
self.class.transaction(:requires_new => requires_new) do
|
|
104
|
+
lock!(requires_lock) if requires_lock
|
|
105
|
+
yield
|
|
109
106
|
end
|
|
110
107
|
end
|
|
111
108
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
def aasm_enum(name=:default)
|
|
110
|
+
case AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
|
111
|
+
when false then nil
|
|
112
|
+
when true then aasm_guess_enum_method(name)
|
|
113
|
+
when nil then aasm_guess_enum_method(name) if aasm_column_looks_like_enum(name)
|
|
114
|
+
else AASM::StateMachineStore.fetch(self.class, true).machine(name).config.enum
|
|
116
115
|
end
|
|
117
116
|
end
|
|
118
|
-
end
|
|
119
117
|
|
|
120
|
-
|
|
118
|
+
def aasm_column_looks_like_enum(name=:default)
|
|
119
|
+
column_name = self.class.aasm(name).attribute_name.to_s
|
|
120
|
+
column = self.class.columns_hash[column_name]
|
|
121
|
+
raise NoMethodError.new("undefined method '#{column_name}' for #{self.class}") if column.nil?
|
|
122
|
+
column.type == :integer
|
|
123
|
+
end
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
#
|
|
125
|
-
# Internally just calls <tt>aasm_read_state</tt>
|
|
126
|
-
#
|
|
127
|
-
# foo = Foo.find(1)
|
|
128
|
-
# foo.aasm_current_state # => :pending
|
|
129
|
-
# foo.aasm_state = "opened"
|
|
130
|
-
# foo.aasm_current_state # => :opened
|
|
131
|
-
# foo.close # => calls aasm_write_state_without_persistence
|
|
132
|
-
# foo.aasm_current_state # => :closed
|
|
133
|
-
# foo.reload
|
|
134
|
-
# foo.aasm_current_state # => :pending
|
|
135
|
-
#
|
|
136
|
-
def aasm_current_state
|
|
137
|
-
@current_state = aasm_read_state
|
|
125
|
+
def aasm_guess_enum_method(name=:default)
|
|
126
|
+
self.class.aasm(name).attribute_name.to_s.pluralize.to_sym
|
|
138
127
|
end
|
|
139
128
|
|
|
140
|
-
|
|
129
|
+
def aasm_raw_attribute_value(state, name=:default)
|
|
130
|
+
if aasm_enum(name)
|
|
131
|
+
self.class.send(aasm_enum(name))[state]
|
|
132
|
+
else
|
|
133
|
+
super
|
|
134
|
+
end
|
|
135
|
+
end
|
|
141
136
|
|
|
142
137
|
# Ensures that if the aasm_state column is nil and the record is new
|
|
143
|
-
#
|
|
138
|
+
# then the initial state gets populated after initialization
|
|
144
139
|
#
|
|
145
140
|
# foo = Foo.new
|
|
146
|
-
# foo.aasm_state # => nil
|
|
147
|
-
# foo.valid?
|
|
148
141
|
# foo.aasm_state # => "open" (where :open is the initial state)
|
|
149
142
|
#
|
|
150
143
|
#
|
|
@@ -155,94 +148,36 @@ module AASM
|
|
|
155
148
|
# foo.aasm_state # => nil
|
|
156
149
|
#
|
|
157
150
|
def aasm_ensure_initial_state
|
|
158
|
-
|
|
151
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
|
152
|
+
# checking via respond_to? does not work in Rails <= 3
|
|
153
|
+
# if respond_to?(self.class.aasm(state_machine_name).attribute_name) && send(self.class.aasm(state_machine_name).attribute_name).blank? # Rails 4
|
|
154
|
+
if aasm_column_is_blank?(state_machine_name)
|
|
155
|
+
aasm(state_machine_name).enter_initial_state
|
|
156
|
+
end
|
|
157
|
+
end
|
|
159
158
|
end
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
#
|
|
166
|
-
# foo = Foo.find(1)
|
|
167
|
-
# foo.aasm_current_state # => :opened
|
|
168
|
-
# foo.close
|
|
169
|
-
# foo.aasm_current_state # => :closed
|
|
170
|
-
# Foo.find(1).aasm_current_state # => :opened
|
|
171
|
-
# foo.save
|
|
172
|
-
# foo.aasm_current_state # => :closed
|
|
173
|
-
# Foo.find(1).aasm_current_state # => :closed
|
|
174
|
-
#
|
|
175
|
-
# NOTE: intended to be called from an event
|
|
176
|
-
def aasm_write_state_without_persistence(state)
|
|
177
|
-
write_attribute(self.class.aasm_column, state.to_s)
|
|
160
|
+
def aasm_column_is_blank?(state_machine_name)
|
|
161
|
+
attribute_name = self.class.aasm(state_machine_name).attribute_name
|
|
162
|
+
attribute_names.include?(attribute_name.to_s) &&
|
|
163
|
+
(send(attribute_name).respond_to?(:empty?) ? !!send(attribute_name).empty? : !send(attribute_name))
|
|
178
164
|
end
|
|
179
|
-
end
|
|
180
165
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# foo.aasm_current_state # => :closed
|
|
189
|
-
# Foo.find(1).aasm_current_state # => :closed
|
|
190
|
-
#
|
|
191
|
-
# NOTE: intended to be called from an event
|
|
192
|
-
def aasm_write_state(state)
|
|
193
|
-
old_value = read_attribute(self.class.aasm_column)
|
|
194
|
-
write_attribute(self.class.aasm_column, state.to_s)
|
|
195
|
-
|
|
196
|
-
unless self.save(false)
|
|
197
|
-
write_attribute(self.class.aasm_column, old_value)
|
|
198
|
-
return false
|
|
166
|
+
def aasm_validate_states
|
|
167
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
|
168
|
+
unless aasm_skipping_validations(state_machine_name)
|
|
169
|
+
if aasm_invalid_state?(state_machine_name)
|
|
170
|
+
self.errors.add(AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.column , "is invalid")
|
|
171
|
+
end
|
|
172
|
+
end
|
|
199
173
|
end
|
|
200
|
-
|
|
201
|
-
true
|
|
202
174
|
end
|
|
203
|
-
end
|
|
204
175
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
# Returns the value of the aasm_column - called from <tt>aasm_current_state</tt>
|
|
208
|
-
#
|
|
209
|
-
# If it's a new record, and the aasm state column is blank it returns the initial state:
|
|
210
|
-
#
|
|
211
|
-
# class Foo < ActiveRecord::Base
|
|
212
|
-
# include AASM
|
|
213
|
-
# aasm_column :status
|
|
214
|
-
# aasm_state :opened
|
|
215
|
-
# aasm_state :closed
|
|
216
|
-
# end
|
|
217
|
-
#
|
|
218
|
-
# foo = Foo.new
|
|
219
|
-
# foo.current_state # => :opened
|
|
220
|
-
# foo.close
|
|
221
|
-
# foo.current_state # => :closed
|
|
222
|
-
#
|
|
223
|
-
# foo = Foo.find(1)
|
|
224
|
-
# foo.current_state # => :opened
|
|
225
|
-
# foo.aasm_state = nil
|
|
226
|
-
# foo.current_state # => nil
|
|
227
|
-
#
|
|
228
|
-
# NOTE: intended to be called from an event
|
|
229
|
-
#
|
|
230
|
-
# This allows for nil aasm states - be sure to add validation to your model
|
|
231
|
-
def aasm_read_state
|
|
232
|
-
if new_record?
|
|
233
|
-
send(self.class.aasm_column).blank? ? aasm_determine_state_name(self.class.aasm_initial_state) : send(self.class.aasm_column).to_sym
|
|
234
|
-
else
|
|
235
|
-
send(self.class.aasm_column).nil? ? nil : send(self.class.aasm_column).to_sym
|
|
236
|
-
end
|
|
176
|
+
def aasm_invalid_state?(state_machine_name)
|
|
177
|
+
aasm(state_machine_name).current_state && !aasm(state_machine_name).states.include?(aasm(state_machine_name).current_state)
|
|
237
178
|
end
|
|
238
|
-
end
|
|
179
|
+
end # InstanceMethods
|
|
239
180
|
|
|
240
|
-
module NamedScopeMethods
|
|
241
|
-
def aasm_state_with_named_scope name, options = {}
|
|
242
|
-
aasm_state_without_named_scope name, options
|
|
243
|
-
self.named_scope name, :conditions => { "#{table_name}.#{self.aasm_column}" => name.to_s} unless self.respond_to?(name)
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
181
|
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
182
|
+
end # Persistence
|
|
183
|
+
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
|