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
|
@@ -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
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
module AASM
|
|
2
|
+
module Persistence
|
|
3
|
+
# This module adds transactional support for any database that supports it.
|
|
4
|
+
# This includes rollback capability and rollback/commit callbacks.
|
|
5
|
+
module ORM
|
|
6
|
+
|
|
7
|
+
# Writes <tt>state</tt> to the state column and persists it to the database
|
|
8
|
+
#
|
|
9
|
+
# foo = Foo.find(1)
|
|
10
|
+
# foo.aasm.current_state # => :opened
|
|
11
|
+
# foo.close!
|
|
12
|
+
# foo.aasm.current_state # => :closed
|
|
13
|
+
# Foo.find(1).aasm.current_state # => :closed
|
|
14
|
+
#
|
|
15
|
+
# NOTE: intended to be called from an event
|
|
16
|
+
def aasm_write_state(state, name=:default)
|
|
17
|
+
attribute_name = self.class.aasm(name).attribute_name
|
|
18
|
+
old_value = aasm_read_attribute(attribute_name)
|
|
19
|
+
aasm_write_state_attribute state, name
|
|
20
|
+
|
|
21
|
+
success = if aasm_skipping_validations(name)
|
|
22
|
+
aasm_update_column(attribute_name, aasm_raw_attribute_value(state, name))
|
|
23
|
+
else
|
|
24
|
+
aasm_save
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
unless success
|
|
28
|
+
aasm_rollback(name, old_value)
|
|
29
|
+
aasm_raise_invalid_record if aasm_whiny_persistence(name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
success
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Writes <tt>state</tt> to the state field, but does not persist it to the database
|
|
36
|
+
#
|
|
37
|
+
# foo = Foo.find(1)
|
|
38
|
+
# foo.aasm.current_state # => :opened
|
|
39
|
+
# foo.close
|
|
40
|
+
# foo.aasm.current_state # => :closed
|
|
41
|
+
# Foo.find(1).aasm.current_state # => :opened
|
|
42
|
+
# foo.save
|
|
43
|
+
# foo.aasm.current_state # => :closed
|
|
44
|
+
# Foo.find(1).aasm.current_state # => :closed
|
|
45
|
+
#
|
|
46
|
+
# NOTE: intended to be called from an event
|
|
47
|
+
def aasm_write_state_without_persistence(state, name=:default)
|
|
48
|
+
aasm_write_state_attribute(state, name)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
# Save the record and return true if it succeeded/false otherwise.
|
|
54
|
+
def aasm_save
|
|
55
|
+
raise("Define #aasm_save_without_error in the AASM Persistence class.")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def aasm_raise_invalid_record
|
|
59
|
+
raise("Define #aasm_raise_invalid_record in the AASM Persistence class.")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Update only the column without running validations.
|
|
63
|
+
def aasm_update_column(attribute_name, value)
|
|
64
|
+
raise("Define #aasm_update_column in the AASM Persistence class.")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def aasm_read_attribute(name)
|
|
68
|
+
raise("Define #aasm_read_attribute the AASM Persistence class.")
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def aasm_write_attribute(name, value)
|
|
72
|
+
raise("Define #aasm_write_attribute in the AASM Persistence class.")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Returns true or false if transaction completed successfully.
|
|
76
|
+
def aasm_transaction(requires_new, requires_lock)
|
|
77
|
+
raise("Define #aasm_transaction the AASM Persistence class.")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def aasm_supports_transactions?
|
|
81
|
+
true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def aasm_execute_after_commit
|
|
85
|
+
yield
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def aasm_write_state_attribute(state, name=:default)
|
|
89
|
+
aasm_write_attribute(self.class.aasm(name).attribute_name, aasm_raw_attribute_value(state, name))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def aasm_raw_attribute_value(state, _name=:default)
|
|
93
|
+
state.to_s
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def aasm_rollback(name, old_value)
|
|
97
|
+
aasm_write_attribute(self.class.aasm(name).attribute_name, old_value)
|
|
98
|
+
false
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def aasm_whiny_persistence(state_machine_name)
|
|
102
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.whiny_persistence
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def aasm_skipping_validations(state_machine_name)
|
|
106
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.skip_validation_on_save
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def use_transactions?(state_machine_name)
|
|
110
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.use_transactions
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def requires_new?(state_machine_name)
|
|
114
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_new_transaction
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def requires_lock?(state_machine_name)
|
|
118
|
+
AASM::StateMachineStore.fetch(self.class, true).machine(state_machine_name).config.requires_lock
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns true if event was fired successfully and transaction completed.
|
|
122
|
+
def aasm_fire_event(state_machine_name, name, options, *args, &block)
|
|
123
|
+
return super unless aasm_supports_transactions? && options[:persist]
|
|
124
|
+
|
|
125
|
+
event = self.class.aasm(state_machine_name).state_machine.events[name]
|
|
126
|
+
event.fire_callbacks(:before_transaction, self, *args)
|
|
127
|
+
event.fire_global_callbacks(:before_all_transactions, self, *args)
|
|
128
|
+
|
|
129
|
+
begin
|
|
130
|
+
success = if options[:persist] && use_transactions?(state_machine_name)
|
|
131
|
+
aasm_transaction(requires_new?(state_machine_name), requires_lock?(state_machine_name)) do
|
|
132
|
+
super
|
|
133
|
+
end
|
|
134
|
+
else
|
|
135
|
+
super
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
if success && !(event.options.keys & [:after_commit, :after_all_commits]).empty?
|
|
139
|
+
aasm_execute_after_commit do
|
|
140
|
+
event.fire_callbacks(:after_commit, self, *args)
|
|
141
|
+
event.fire_global_callbacks(:after_all_commits, self, *args)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
success
|
|
146
|
+
ensure
|
|
147
|
+
event.fire_callbacks(:after_transaction, self, *args)
|
|
148
|
+
event.fire_global_callbacks(:after_all_transactions, self, *args)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end # Transactional
|
|
153
|
+
end # Persistence
|
|
154
|
+
end # AASM
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module AASM
|
|
2
|
+
module Persistence
|
|
3
|
+
module PlainPersistence
|
|
4
|
+
|
|
5
|
+
# may be overwritten by persistence mixins
|
|
6
|
+
def aasm_read_state(name=:default)
|
|
7
|
+
# all the following lines behave like @current_state ||= aasm(name).enter_initial_state
|
|
8
|
+
current = aasm(name).instance_variable_defined?("@current_state_#{name}") &&
|
|
9
|
+
aasm(name).instance_variable_get("@current_state_#{name}")
|
|
10
|
+
return current if current
|
|
11
|
+
aasm(name).instance_variable_set("@current_state_#{name}", aasm(name).enter_initial_state)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# may be overwritten by persistence mixins
|
|
15
|
+
def aasm_write_state(new_state, name=:default)
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# may be overwritten by persistence mixins
|
|
20
|
+
def aasm_write_state_without_persistence(new_state, name=:default)
|
|
21
|
+
aasm(name).instance_variable_set("@current_state_#{name}", new_state)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module AASM
|
|
2
|
+
module Persistence
|
|
3
|
+
module RedisPersistence
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.send(:include, AASM::Persistence::Base)
|
|
7
|
+
base.send(:include, AASM::Persistence::RedisPersistence::InstanceMethods)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module InstanceMethods
|
|
11
|
+
# Initialize with default values
|
|
12
|
+
#
|
|
13
|
+
# Redis::Objects removes the key from Redis when set to `nil`
|
|
14
|
+
def initialize(*args)
|
|
15
|
+
super
|
|
16
|
+
aasm_ensure_initial_state
|
|
17
|
+
end
|
|
18
|
+
# Returns the value of the aasm.attribute_name - called from <tt>aasm.current_state</tt>
|
|
19
|
+
#
|
|
20
|
+
# If it's a new record, and the aasm state column is blank it returns the initial state
|
|
21
|
+
#
|
|
22
|
+
# class Foo
|
|
23
|
+
# include Redis::Objects
|
|
24
|
+
# include AASM
|
|
25
|
+
# aasm :column => :status do
|
|
26
|
+
# state :opened
|
|
27
|
+
# state :closed
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# foo = Foo.new
|
|
32
|
+
# foo.current_state # => :opened
|
|
33
|
+
# foo.close
|
|
34
|
+
# foo.current_state # => :closed
|
|
35
|
+
#
|
|
36
|
+
# foo = Foo[1]
|
|
37
|
+
# foo.current_state # => :opened
|
|
38
|
+
# foo.aasm_state = nil
|
|
39
|
+
# foo.current_state # => nil
|
|
40
|
+
#
|
|
41
|
+
# NOTE: intended to be called from an event
|
|
42
|
+
#
|
|
43
|
+
# This allows for nil aasm states - be sure to add validation to your model
|
|
44
|
+
def aasm_read_state(name=:default)
|
|
45
|
+
state = send(self.class.aasm(name).attribute_name)
|
|
46
|
+
|
|
47
|
+
if state.value.nil?
|
|
48
|
+
nil
|
|
49
|
+
else
|
|
50
|
+
state.value.to_sym
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Ensures that if the aasm_state column is nil and the record is new
|
|
55
|
+
# that the initial state gets populated before validation on create
|
|
56
|
+
#
|
|
57
|
+
# foo = Foo.new
|
|
58
|
+
# foo.aasm_state # => nil
|
|
59
|
+
# foo.valid?
|
|
60
|
+
# foo.aasm_state # => "open" (where :open is the initial state)
|
|
61
|
+
#
|
|
62
|
+
#
|
|
63
|
+
# foo = Foo.find(:first)
|
|
64
|
+
# foo.aasm_state # => 1
|
|
65
|
+
# foo.aasm_state = nil
|
|
66
|
+
# foo.valid?
|
|
67
|
+
# foo.aasm_state # => nil
|
|
68
|
+
#
|
|
69
|
+
def aasm_ensure_initial_state
|
|
70
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |name|
|
|
71
|
+
aasm_column = self.class.aasm(name).attribute_name
|
|
72
|
+
aasm(name).enter_initial_state if !send(aasm_column).value || send(aasm_column).value.empty?
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Writes <tt>state</tt> to the state column and persists it to the database
|
|
77
|
+
#
|
|
78
|
+
# foo = Foo[1]
|
|
79
|
+
# foo.aasm.current_state # => :opened
|
|
80
|
+
# foo.close!
|
|
81
|
+
# foo.aasm.current_state # => :closed
|
|
82
|
+
# Foo[1].aasm.current_state # => :closed
|
|
83
|
+
#
|
|
84
|
+
# NOTE: intended to be called from an event
|
|
85
|
+
def aasm_write_state(state, name=:default)
|
|
86
|
+
aasm_column = self.class.aasm(name).attribute_name
|
|
87
|
+
send("#{aasm_column}").value = state
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Writes <tt>state</tt> to the state column, but does not persist it to the database
|
|
91
|
+
# (but actually it still does)
|
|
92
|
+
#
|
|
93
|
+
# With Redis::Objects it's not possible to skip persisting - it's not an ORM,
|
|
94
|
+
# it does not operate like an AR model and does not know how to postpone changes.
|
|
95
|
+
#
|
|
96
|
+
# foo = Foo[1]
|
|
97
|
+
# foo.aasm.current_state # => :opened
|
|
98
|
+
# foo.close
|
|
99
|
+
# foo.aasm.current_state # => :closed
|
|
100
|
+
# Foo[1].aasm.current_state # => :opened
|
|
101
|
+
# foo.save
|
|
102
|
+
# foo.aasm.current_state # => :closed
|
|
103
|
+
# Foo[1].aasm.current_state # => :closed
|
|
104
|
+
#
|
|
105
|
+
# NOTE: intended to be called from an event
|
|
106
|
+
def aasm_write_state_without_persistence(state, name=:default)
|
|
107
|
+
aasm_write_state(state, name)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'aasm/persistence/orm'
|
|
2
|
+
module AASM
|
|
3
|
+
module Persistence
|
|
4
|
+
module SequelPersistence
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.send(:include, AASM::Persistence::Base)
|
|
7
|
+
base.send(:include, AASM::Persistence::ORM)
|
|
8
|
+
base.send(:include, AASM::Persistence::SequelPersistence::InstanceMethods)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module InstanceMethods
|
|
12
|
+
def before_validation
|
|
13
|
+
aasm_ensure_initial_state
|
|
14
|
+
super
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def before_create
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def aasm_raise_invalid_record
|
|
22
|
+
raise Sequel::ValidationFailed.new(self)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def aasm_new_record?
|
|
26
|
+
new?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Returns nil if fails silently
|
|
30
|
+
# http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model/InstanceMethods.html#method-i-save
|
|
31
|
+
def aasm_save
|
|
32
|
+
!save(raise_on_failure: false).nil?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def aasm_read_attribute(name)
|
|
36
|
+
send(name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def aasm_write_attribute(name, value)
|
|
40
|
+
send("#{name}=", value)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def aasm_transaction(requires_new, requires_lock)
|
|
44
|
+
self.class.db.transaction(savepoint: requires_new) do
|
|
45
|
+
if requires_lock
|
|
46
|
+
# http://sequel.jeremyevans.net/rdoc/classes/Sequel/Model/InstanceMethods.html#method-i-lock-21
|
|
47
|
+
requires_lock.is_a?(String) ? lock!(requires_lock) : lock!
|
|
48
|
+
end
|
|
49
|
+
yield
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def aasm_update_column(attribute_name, value)
|
|
54
|
+
this.update(attribute_name => value)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Ensures that if the aasm_state column is nil and the record is new
|
|
58
|
+
# that the initial state gets populated before validation on create
|
|
59
|
+
#
|
|
60
|
+
# foo = Foo.new
|
|
61
|
+
# foo.aasm_state # => nil
|
|
62
|
+
# foo.valid?
|
|
63
|
+
# foo.aasm_state # => "open" (where :open is the initial state)
|
|
64
|
+
#
|
|
65
|
+
#
|
|
66
|
+
# foo = Foo.find(:first)
|
|
67
|
+
# foo.aasm_state # => 1
|
|
68
|
+
# foo.aasm_state = nil
|
|
69
|
+
# foo.valid?
|
|
70
|
+
# foo.aasm_state # => nil
|
|
71
|
+
#
|
|
72
|
+
def aasm_ensure_initial_state
|
|
73
|
+
AASM::StateMachineStore.fetch(self.class, true).machine_names.each do |state_machine_name|
|
|
74
|
+
aasm(state_machine_name).enter_initial_state if
|
|
75
|
+
(new? || values.key?(self.class.aasm(state_machine_name).attribute_name)) &&
|
|
76
|
+
send(self.class.aasm(state_machine_name).attribute_name).to_s.strip.empty?
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
data/lib/aasm/persistence.rb
CHANGED
|
@@ -1,16 +1,54 @@
|
|
|
1
1
|
module AASM
|
|
2
2
|
module Persistence
|
|
3
|
+
class << self
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# Use a fancier auto-loading thingy, perhaps. When there are more persistence engines.
|
|
8
|
-
hierarchy = base.ancestors.map {|klass| klass.to_s}
|
|
5
|
+
def load_persistence(base)
|
|
6
|
+
# Use a fancier auto-loading thingy, perhaps. When there are more persistence engines.
|
|
7
|
+
hierarchy = base.ancestors.map {|klass| klass.to_s}
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
if hierarchy.include?("ActiveRecord::Base")
|
|
10
|
+
require_persistence :active_record
|
|
11
|
+
include_persistence base, :active_record
|
|
12
|
+
elsif hierarchy.include?("Mongoid::Document")
|
|
13
|
+
require_persistence :mongoid
|
|
14
|
+
include_persistence base, :mongoid
|
|
15
|
+
elsif hierarchy.include?("NoBrainer::Document")
|
|
16
|
+
require_persistence :no_brainer
|
|
17
|
+
include_persistence base, :no_brainer
|
|
18
|
+
elsif hierarchy.include?("Sequel::Model")
|
|
19
|
+
require_persistence :sequel
|
|
20
|
+
include_persistence base, :sequel
|
|
21
|
+
elsif hierarchy.include?("Dynamoid::Document")
|
|
22
|
+
require_persistence :dynamoid
|
|
23
|
+
include_persistence base, :dynamoid
|
|
24
|
+
elsif hierarchy.include?("Redis::Objects")
|
|
25
|
+
require_persistence :redis
|
|
26
|
+
include_persistence base, :redis
|
|
27
|
+
elsif hierarchy.include?("CDQManagedObject")
|
|
28
|
+
include_persistence base, :core_data_query
|
|
29
|
+
else
|
|
30
|
+
include_persistence base, :plain
|
|
31
|
+
end
|
|
13
32
|
end
|
|
14
|
-
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def require_persistence(type)
|
|
37
|
+
require File.join(File.dirname(__FILE__), 'persistence', "#{type}_persistence")
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def include_persistence(base, type)
|
|
41
|
+
base.send(:include, constantize("#{capitalize(type)}Persistence"))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def capitalize(string_or_symbol)
|
|
45
|
+
string_or_symbol.to_s.split('_').map {|segment| segment[0].upcase + segment[1..-1]}.join('')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def constantize(string)
|
|
49
|
+
AASM::Persistence.const_get(string)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end # class << self
|
|
15
53
|
end
|
|
16
|
-
end
|
|
54
|
+
end # AASM
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
RSpec::Matchers.define :allow_event do |event|
|
|
2
|
+
match do |obj|
|
|
3
|
+
@state_machine_name ||= :default
|
|
4
|
+
obj.aasm(@state_machine_name).may_fire_event?(event, *@args)
|
|
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 event #{expected} (on :#{@state_machine_name})"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
failure_message do |obj|
|
|
20
|
+
"expected that the event :#{expected} would be allowed (on :#{@state_machine_name})"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
failure_message_when_negated do |obj|
|
|
24
|
+
"expected that the event :#{expected} would not be allowed (on :#{@state_machine_name})"
|
|
25
|
+
end
|
|
26
|
+
end
|