state_machines-activemodel 0.0.2 → 0.0.3
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +14 -10
- data/Appraisals +4 -15
- data/Gemfile +3 -0
- data/LICENSE.txt +1 -1
- data/README.md +9 -6
- data/Rakefile +5 -6
- data/gemfiles/active_model_4.1.gemfile +5 -1
- data/gemfiles/active_model_4.2.gemfile +11 -0
- data/lib/state_machines/integrations/active_model.rb +105 -108
- data/lib/state_machines/integrations/active_model/locale.rb +8 -8
- data/lib/state_machines/integrations/{version.rb → active_model/version.rb} +1 -1
- data/state_machines-activemodel.gemspec +10 -9
- data/{spec/support → test/files}/en.yml +1 -1
- data/test/integration_test.rb +23 -0
- data/test/machine_by_default_test.rb +24 -0
- data/test/machine_errors_test.rb +19 -0
- data/test/machine_multiple_test.rb +18 -0
- data/test/machine_with_callbacks_test.rb +130 -0
- data/test/machine_with_dirty_attribute_and_custom_attributes_during_loopback_test.rb +26 -0
- data/test/machine_with_dirty_attribute_and_state_events_test.rb +23 -0
- data/test/machine_with_dirty_attributes_and_custom_attribute_test.rb +34 -0
- data/test/machine_with_dirty_attributes_during_loopback_test.rb +49 -0
- data/test/machine_with_dirty_attributes_test.rb +33 -0
- data/test/machine_with_dynamic_initial_state_test.rb +14 -0
- data/test/machine_with_events_test.rb +13 -0
- data/test/machine_with_failed_after_callbacks_test.rb +31 -0
- data/test/machine_with_failed_before_callbacks_test.rb +32 -0
- data/test/machine_with_initialized_state_test.rb +35 -0
- data/test/machine_with_internationalization_test.rb +190 -0
- data/test/machine_with_model_state_attribute_test.rb +31 -0
- data/test/machine_with_non_model_state_attribute_undefined_test.rb +26 -0
- data/test/machine_with_state_driven_validations_test.rb +31 -0
- data/test/machine_with_states_test.rb +13 -0
- data/test/machine_with_static_initial_state_test.rb +13 -0
- data/test/machine_with_validations_and_custom_attribute_test.rb +22 -0
- data/test/machine_with_validations_test.rb +46 -0
- data/test/test_helper.rb +58 -0
- metadata +83 -36
- data/gemfiles/active_model_3.2.gemfile +0 -7
- data/gemfiles/active_model_3.2.gemfile.lock +0 -50
- data/gemfiles/active_model_4.0.gemfile +0 -7
- data/gemfiles/active_model_4.0.gemfile.lock +0 -56
- data/gemfiles/active_model_4.1.gemfile.lock +0 -57
- data/gemfiles/active_model_edge.gemfile +0 -7
- data/gemfiles/active_model_edge.gemfile.lock +0 -62
- data/spec/active_model_spec.rb +0 -801
- data/spec/integration_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -8
- data/spec/support/helpers.rb +0 -48
- data/spec/support/migration_helpers.rb +0 -43
@@ -1,11 +1,11 @@
|
|
1
|
-
{:
|
2
|
-
:
|
3
|
-
:
|
4
|
-
:
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
1
|
+
{ en: {
|
2
|
+
activemodel: {
|
3
|
+
errors: {
|
4
|
+
messages: {
|
5
|
+
invalid: StateMachines::Machine.default_messages[:invalid],
|
6
|
+
invalid_event: StateMachines::Machine.default_messages[:invalid_event] % ['%{state}'],
|
7
|
+
invalid_transition: StateMachines::Machine.default_messages[:invalid_transition] % ['%{event}']
|
8
8
|
}
|
9
9
|
}
|
10
10
|
}
|
11
|
-
}}
|
11
|
+
} }
|
@@ -1,27 +1,28 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'state_machines/integrations/version'
|
4
|
+
require 'state_machines/integrations/active_model/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'state_machines-activemodel'
|
8
8
|
spec.version = StateMachines::Integrations::ActiveModel::VERSION
|
9
9
|
spec.authors = ['Abdelkader Boudih', 'Aaron Pfeifer']
|
10
|
-
spec.email =
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
spec.homepage = 'https://github.com/
|
10
|
+
spec.email = %w(terminale@gmail.com aaron@pluginaweek.org)
|
11
|
+
spec.summary = 'ActiveModel integration for State Machines'
|
12
|
+
spec.description = 'Adds support for creating state machines for attributes on ActiveModel'
|
13
|
+
spec.homepage = 'https://github.com/state-machines/state_machines-activemodel'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.test_files = spec.files.grep(/^
|
17
|
+
spec.test_files = spec.files.grep(/^test\//)
|
18
18
|
spec.require_paths = ['lib']
|
19
19
|
spec.required_ruby_version = '>= 1.9.3'
|
20
|
-
spec.add_dependency 'state_machines'
|
21
|
-
spec.add_dependency 'activemodel'
|
20
|
+
spec.add_dependency 'state_machines', '~> 0.1.0'
|
21
|
+
spec.add_dependency 'activemodel', '~> 4.1'
|
22
22
|
|
23
23
|
spec.add_development_dependency 'bundler', '>= 1.6'
|
24
24
|
spec.add_development_dependency 'rake', '>= 10'
|
25
25
|
spec.add_development_dependency 'appraisal', '>= 1'
|
26
|
-
spec.add_development_dependency '
|
26
|
+
spec.add_development_dependency 'minitest', '~> 5.4'
|
27
|
+
spec.add_development_dependency 'minitest-reporters'
|
27
28
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class IntegrationTest < BaseTestCase
|
4
|
+
def test_should_be_registred
|
5
|
+
assert_includes StateMachines::Integrations.list, StateMachines::Integrations::ActiveModel
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_should_have_an_integration_name
|
9
|
+
assert_equal :active_model, StateMachines::Integrations::ActiveModel.integration_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_match_if_class_includes_validations_feature
|
13
|
+
assert StateMachines::Integrations::ActiveModel.matches?(new_model { include ActiveModel::Validations })
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_not_match_if_class_does_not_include_active_model_features
|
17
|
+
refute StateMachines::Integrations::ActiveModel.matches?(new_model)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_have_no_defaults
|
21
|
+
assert_equal({}, StateMachines::Integrations::ActiveModel.defaults)
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineByDefaultTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model
|
6
|
+
@machine = StateMachines::Machine.new(@model, integration: :active_model)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_should_not_have_action
|
10
|
+
assert_nil @machine.action
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_use_transactions
|
14
|
+
assert_equal true, @machine.use_transactions
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_should_not_have_any_before_callbacks
|
18
|
+
assert_equal 0, @machine.callbacks[:before].size
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_should_not_have_any_after_callbacks
|
22
|
+
assert_equal 0, @machine.callbacks[:after].size
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineErrorsTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model { include ActiveModel::Validations }
|
6
|
+
@machine = StateMachines::Machine.new(@model)
|
7
|
+
@record = @model.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_should_be_able_to_describe_current_errors
|
11
|
+
@record.errors.add(:id, 'cannot be blank')
|
12
|
+
@record.errors.add(:state, 'is invalid')
|
13
|
+
assert_equal ['Id cannot be blank', 'State is invalid'], @machine.errors_for(@record).split(', ').sort
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_describe_as_halted_with_no_errors
|
17
|
+
assert_equal 'Transition halted', @machine.errors_for(@record)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineMultipleTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
model_attribute :status
|
7
|
+
end
|
8
|
+
|
9
|
+
@state_machine = StateMachines::Machine.new(@model, initial: :parked, integration: :active_model)
|
10
|
+
@status_machine = StateMachines::Machine.new(@model, :status, initial: :idling, integration: :active_model)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_should_should_initialize_each_state
|
14
|
+
record = @model.new
|
15
|
+
assert_equal 'parked', record.state
|
16
|
+
assert_equal 'idling', record.status
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithCallbacksTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model
|
6
|
+
@machine = StateMachines::Machine.new(@model, initial: :parked, integration: :active_model)
|
7
|
+
@machine.other_states :idling
|
8
|
+
@machine.event :ignite
|
9
|
+
|
10
|
+
@record = @model.new(state: 'parked')
|
11
|
+
@transition = StateMachines::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_run_before_callbacks
|
15
|
+
called = false
|
16
|
+
@machine.before_transition { called = true }
|
17
|
+
|
18
|
+
@transition.perform
|
19
|
+
assert called
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_pass_record_to_before_callbacks_with_one_argument
|
23
|
+
record = nil
|
24
|
+
@machine.before_transition { |arg| record = arg }
|
25
|
+
|
26
|
+
@transition.perform
|
27
|
+
assert_equal @record, record
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_pass_record_and_transition_to_before_callbacks_with_multiple_arguments
|
31
|
+
callback_args = nil
|
32
|
+
@machine.before_transition { |*args| callback_args = args }
|
33
|
+
|
34
|
+
@transition.perform
|
35
|
+
assert_equal [@record, @transition], callback_args
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_should_run_before_callbacks_outside_the_context_of_the_record
|
39
|
+
context = nil
|
40
|
+
@machine.before_transition { context = self }
|
41
|
+
|
42
|
+
@transition.perform
|
43
|
+
assert_equal self, context
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_run_after_callbacks
|
47
|
+
called = false
|
48
|
+
@machine.after_transition { called = true }
|
49
|
+
|
50
|
+
@transition.perform
|
51
|
+
assert called
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_should_pass_record_to_after_callbacks_with_one_argument
|
55
|
+
record = nil
|
56
|
+
@machine.after_transition { |arg| record = arg }
|
57
|
+
|
58
|
+
@transition.perform
|
59
|
+
assert_equal @record, record
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_should_pass_record_and_transition_to_after_callbacks_with_multiple_arguments
|
63
|
+
callback_args = nil
|
64
|
+
@machine.after_transition { |*args| callback_args = args }
|
65
|
+
|
66
|
+
@transition.perform
|
67
|
+
assert_equal [@record, @transition], callback_args
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_should_run_after_callbacks_outside_the_context_of_the_record
|
71
|
+
context = nil
|
72
|
+
@machine.after_transition { context = self }
|
73
|
+
|
74
|
+
@transition.perform
|
75
|
+
assert_equal self, context
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_should_run_around_callbacks
|
79
|
+
before_called = false
|
80
|
+
after_called = false
|
81
|
+
ensure_called = 0
|
82
|
+
@machine.around_transition do |block|
|
83
|
+
before_called = true
|
84
|
+
begin
|
85
|
+
block.call
|
86
|
+
ensure
|
87
|
+
ensure_called += 1
|
88
|
+
end
|
89
|
+
after_called = true
|
90
|
+
end
|
91
|
+
|
92
|
+
@transition.perform
|
93
|
+
assert before_called
|
94
|
+
assert after_called
|
95
|
+
assert_equal ensure_called, 1
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_should_include_transition_states_in_known_states
|
99
|
+
@machine.before_transition to: :first_gear, do: lambda {}
|
100
|
+
|
101
|
+
assert_equal [:parked, :idling, :first_gear], @machine.states.map { |state| state.name }
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_should_allow_symbolic_callbacks
|
105
|
+
callback_args = nil
|
106
|
+
|
107
|
+
klass = class << @record
|
108
|
+
self
|
109
|
+
end
|
110
|
+
klass.send(:define_method, :after_ignite) do |*args|
|
111
|
+
callback_args = args
|
112
|
+
end
|
113
|
+
|
114
|
+
@machine.before_transition(:after_ignite)
|
115
|
+
|
116
|
+
@transition.perform
|
117
|
+
assert_equal [@transition], callback_args
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_should_allow_string_callbacks
|
121
|
+
class << @record
|
122
|
+
attr_reader :callback_result
|
123
|
+
end
|
124
|
+
|
125
|
+
@machine.before_transition('@callback_result = [1, 2, 3]')
|
126
|
+
@transition.perform
|
127
|
+
|
128
|
+
assert_equal [1, 2, 3], @record.callback_result
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithDirtyAttributeAndCustomAttributesDuringLoopbackTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
include ActiveModel::Dirty
|
7
|
+
model_attribute :status
|
8
|
+
define_attribute_methods [:status]
|
9
|
+
end
|
10
|
+
@machine = StateMachines::Machine.new(@model, :status, initial: :parked)
|
11
|
+
@machine.event :park
|
12
|
+
|
13
|
+
@record = @model.create
|
14
|
+
|
15
|
+
@transition = StateMachines::Transition.new(@record, @machine, :park, :parked, :parked)
|
16
|
+
@transition.perform
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_not_include_state_in_changed_attributes
|
20
|
+
assert_equal [], @record.changed
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_not_track_attribute_changes
|
24
|
+
assert_equal nil, @record.changes['status']
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithDirtyAttributeAndStateEventsTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
include ActiveModel::Dirty
|
7
|
+
define_attribute_methods [:state]
|
8
|
+
end
|
9
|
+
@machine = StateMachines::Machine.new(@model, action: :save, initial: :parked)
|
10
|
+
@machine.event :ignite
|
11
|
+
|
12
|
+
@record = @model.create
|
13
|
+
@record.state_event = 'ignite'
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_should_not_include_state_in_changed_attributes
|
17
|
+
assert_equal [], @record.changed
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_not_track_attribute_change
|
21
|
+
assert_equal nil, @record.changes['state']
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithDirtyAttributesAndCustomAttributeTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
include ActiveModel::Dirty
|
7
|
+
model_attribute :status
|
8
|
+
define_attribute_methods [:status]
|
9
|
+
end
|
10
|
+
@machine = StateMachines::Machine.new(@model, :status, initial: :parked)
|
11
|
+
@machine.event :ignite
|
12
|
+
@machine.state :idling
|
13
|
+
|
14
|
+
@record = @model.create
|
15
|
+
|
16
|
+
@transition = StateMachines::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
17
|
+
@transition.perform
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_include_state_in_changed_attributes
|
21
|
+
assert_equal %w(status), @record.changed
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_track_attribute_change
|
25
|
+
assert_equal %w(parked idling), @record.changes['status']
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_should_not_reset_changes_on_multiple_transitions
|
29
|
+
transition = StateMachines::Transition.new(@record, @machine, :ignite, :idling, :idling)
|
30
|
+
transition.perform
|
31
|
+
|
32
|
+
assert_equal %w(parked idling), @record.changes['status']
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithDirtyAttributesDuringLoopbackTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
include ActiveModel::Dirty
|
7
|
+
define_attribute_methods [:state]
|
8
|
+
end
|
9
|
+
@machine = StateMachines::Machine.new(@model, initial: :parked)
|
10
|
+
@machine.event :park
|
11
|
+
|
12
|
+
@record = @model.create
|
13
|
+
|
14
|
+
@transition = StateMachines::Transition.new(@record, @machine, :park, :parked, :parked)
|
15
|
+
@transition.perform
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_not_include_state_in_changed_attributes
|
19
|
+
assert_equal [], @record.changed
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_not_track_attribute_changes
|
23
|
+
assert_equal nil, @record.changes['state']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
class MachineWithDirtyAttributeAndCustomAttributesDuringLoopbackTest < BaseTestCase
|
27
|
+
def setup
|
28
|
+
@model = new_model do
|
29
|
+
include ActiveModel::Dirty
|
30
|
+
model_attribute :status
|
31
|
+
define_attribute_methods [:status]
|
32
|
+
end
|
33
|
+
@machine = StateMachines::Machine.new(@model, :status, initial: :parked)
|
34
|
+
@machine.event :park
|
35
|
+
|
36
|
+
@record = @model.create
|
37
|
+
|
38
|
+
@transition = StateMachines::Transition.new(@record, @machine, :park, :parked, :parked)
|
39
|
+
@transition.perform
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_should_not_include_state_in_changed_attributes
|
43
|
+
assert_equal [], @record.changed
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_should_not_track_attribute_changes
|
47
|
+
assert_equal nil, @record.changes['status']
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MachineWithDirtyAttributesTest < BaseTestCase
|
4
|
+
def setup
|
5
|
+
@model = new_model do
|
6
|
+
include ActiveModel::Dirty
|
7
|
+
define_attribute_methods [:state]
|
8
|
+
end
|
9
|
+
@machine = StateMachines::Machine.new(@model, initial: :parked)
|
10
|
+
@machine.event :ignite
|
11
|
+
@machine.state :idling
|
12
|
+
|
13
|
+
@record = @model.create
|
14
|
+
|
15
|
+
@transition = StateMachines::Transition.new(@record, @machine, :ignite, :parked, :idling)
|
16
|
+
@transition.perform
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_include_state_in_changed_attributes
|
20
|
+
assert_equal %w(state), @record.changed
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_track_attribute_change
|
24
|
+
assert_equal %w(parked idling), @record.changes['state']
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_not_reset_changes_on_multiple_transitions
|
28
|
+
transition = StateMachines::Transition.new(@record, @machine, :ignite, :idling, :idling)
|
29
|
+
transition.perform
|
30
|
+
|
31
|
+
assert_equal %w(parked idling), @record.changes['state']
|
32
|
+
end
|
33
|
+
end
|