state_machines-activerecord 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +20 -0
  4. data/Appraisals +11 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +65 -0
  8. data/Rakefile +9 -0
  9. data/gemfiles/active_record_4.1.gemfile +13 -0
  10. data/gemfiles/active_record_4.2.gemfile +13 -0
  11. data/lib/state_machines-activerecord.rb +1 -0
  12. data/lib/state_machines/integrations/active_record.rb +588 -0
  13. data/lib/state_machines/integrations/active_record/locale.rb +12 -0
  14. data/lib/state_machines/integrations/active_record/version.rb +7 -0
  15. data/log/.gitkeep +0 -0
  16. data/state_machines-activerecord.gemspec +27 -0
  17. data/test/files/en.yml +5 -0
  18. data/test/files/models/post.rb +11 -0
  19. data/test/integration_test.rb +23 -0
  20. data/test/machine_by_default_test.rb +16 -0
  21. data/test/machine_errors_test.rb +19 -0
  22. data/test/machine_multiple_test.rb +17 -0
  23. data/test/machine_nested_action_test.rb +38 -0
  24. data/test/machine_unmigrated_test.rb +14 -0
  25. data/test/machine_with_aliased_attribute_test.rb +23 -0
  26. data/test/machine_with_callbacks_test.rb +172 -0
  27. data/test/machine_with_column_state_attribute_test.rb +44 -0
  28. data/test/machine_with_complex_pluralization_scopes_test.rb +16 -0
  29. data/test/machine_with_conflicting_predicate_test.rb +18 -0
  30. data/test/machine_with_conflicting_state_name_test.rb +29 -0
  31. data/test/machine_with_custom_attribute_test.rb +21 -0
  32. data/test/machine_with_default_scope_test.rb +18 -0
  33. data/test/machine_with_different_column_default_test.rb +27 -0
  34. data/test/machine_with_different_integer_column_default_test.rb +29 -0
  35. data/test/machine_with_dirty_attribute_and_custom_attributes_during_loopback_test.rb +24 -0
  36. data/test/machine_with_dirty_attribute_and_state_events_test.rb +20 -0
  37. data/test/machine_with_dirty_attributes_and_custom_attribute_test.rb +32 -0
  38. data/test/machine_with_dirty_attributes_during_loopback_test.rb +22 -0
  39. data/test/machine_with_dirty_attributes_test.rb +35 -0
  40. data/test/machine_with_dynamic_initial_state_test.rb +99 -0
  41. data/test/machine_with_event_attributes_on_autosave_test.rb +48 -0
  42. data/test/machine_with_event_attributes_on_custom_action_test.rb +41 -0
  43. data/test/machine_with_event_attributes_on_save_bang_test.rb +82 -0
  44. data/test/machine_with_event_attributes_on_save_test.rb +184 -0
  45. data/test/machine_with_event_attributes_on_validation_test.rb +126 -0
  46. data/test/machine_with_events_test.rb +13 -0
  47. data/test/machine_with_failed_action_test.rb +40 -0
  48. data/test/machine_with_failed_after_callbacks_test.rb +35 -0
  49. data/test/machine_with_failed_before_callbacks_test.rb +36 -0
  50. data/test/machine_with_initialized_state_test.rb +35 -0
  51. data/test/machine_with_internationalization_test.rb +180 -0
  52. data/test/machine_with_loopback_test.rb +22 -0
  53. data/test/machine_with_non_column_state_attribute_defined_test.rb +35 -0
  54. data/test/machine_with_non_column_state_attribute_undefined_test.rb +33 -0
  55. data/test/machine_with_same_column_default_test.rb +26 -0
  56. data/test/machine_with_scopes_and_joins_test.rb +37 -0
  57. data/test/machine_with_scopes_and_owner_subclass_test.rb +27 -0
  58. data/test/machine_with_scopes_test.rb +70 -0
  59. data/test/machine_with_state_driven_validations_test.rb +30 -0
  60. data/test/machine_with_states_test.rb +13 -0
  61. data/test/machine_with_static_initial_state_test.rb +166 -0
  62. data/test/machine_with_transactions_test.rb +26 -0
  63. data/test/machine_with_validations_and_custom_attribute_test.rb +21 -0
  64. data/test/machine_with_validations_test.rb +47 -0
  65. data/test/machine_without_database_test.rb +20 -0
  66. data/test/machine_without_transactions_test.rb +26 -0
  67. data/test/model_test.rb +12 -0
  68. data/test/test_helper.rb +42 -0
  69. metadata +264 -0
@@ -0,0 +1,16 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithComplexPluralizationScopesTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model, :status)
7
+ end
8
+
9
+ def test_should_create_singular_with_scope
10
+ assert @model.respond_to?(:with_status)
11
+ end
12
+
13
+ def test_should_create_plural_with_scope
14
+ assert @model.respond_to?(:with_statuses)
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithConflictingPredicateTest < BaseTestCase
4
+ def setup
5
+ @model = new_model do
6
+ def state?(*args)
7
+ true
8
+ end
9
+ end
10
+
11
+ @machine = StateMachines::Machine.new(@model)
12
+ @record = @model.new
13
+ end
14
+
15
+ def test_should_not_define_attribute_predicate
16
+ assert @record.state?
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'test_helper'
2
+ require 'stringio'
3
+
4
+ class MachineWithConflictingStateNameTest < BaseTestCase
5
+ def setup
6
+ @original_stderr, $stderr = $stderr, StringIO.new
7
+
8
+ @model = new_model
9
+ end
10
+
11
+ def test_should_output_warning_with_same_machine_name
12
+ @machine = StateMachines::Machine.new(@model)
13
+ @machine.state :state
14
+
15
+ assert_match(/^Instance method "state\?" is already defined in Foo, use generic helper instead.*\n$/, $stderr.string)
16
+ end
17
+
18
+ def test_should_output_warning_with_same_machine_attribute
19
+ @machine = StateMachines::Machine.new(@model, :public_state, :attribute => :state)
20
+ @machine.state :state
21
+
22
+ assert_match(/^Instance method "state\?" is already defined in Foo, use generic helper instead.*\n$/, $stderr.string)
23
+ end
24
+
25
+ def teardown
26
+ $stderr = @original_stderr
27
+ super
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require_relative 'test_helper'
2
+ require 'stringio'
3
+
4
+ class MachineWithCustomAttributeTest < BaseTestCase
5
+ def setup
6
+ @original_stderr, $stderr = $stderr, StringIO.new
7
+
8
+ @model = new_model
9
+ @machine = StateMachines::Machine.new(@model, :public_state, :attribute => :state)
10
+ @record = @model.new
11
+ end
12
+
13
+ def test_should_not_delegate_attribute_predicate_with_different_attribute
14
+ assert_raise(ArgumentError) { @record.public_state? }
15
+ end
16
+
17
+ def teardown
18
+ $stderr = @original_stderr
19
+ super
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDefaultScopeTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model, :initial => :parked)
7
+ @machine.state :idling
8
+
9
+ @model.class_eval do
10
+ default_scope { with_state(:parked, :idling) }
11
+ end
12
+ end
13
+
14
+ def test_should_set_initial_state_on_created_object
15
+ object = @model.new
16
+ assert_equal 'parked', object.state
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'test_helper'
2
+ require 'stringio'
3
+
4
+ class MachineWithDifferentColumnDefaultTest < BaseTestCase
5
+ def setup
6
+ @original_stderr, $stderr = $stderr, StringIO.new
7
+
8
+ @model = new_model do
9
+ connection.add_column table_name, :status, :string, :default => 'idling'
10
+ end
11
+ @machine = StateMachines::Machine.new(@model, :status, :initial => :parked)
12
+ @record = @model.new
13
+ end
14
+
15
+ def test_should_use_machine_default
16
+ assert_equal 'parked', @record.status
17
+ end
18
+
19
+ def test_should_generate_a_warning
20
+ assert_match(/Both Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
21
+ end
22
+
23
+ def teardown
24
+ $stderr = @original_stderr
25
+ super
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ require_relative 'test_helper'
2
+ require 'stringio'
3
+
4
+ class MachineWithDifferentIntegerColumnDefaultTest < BaseTestCase
5
+ def setup
6
+ @original_stderr, $stderr = $stderr, StringIO.new
7
+
8
+ @model = new_model do
9
+ connection.add_column table_name, :status, :integer, :default => 0
10
+ end
11
+ @machine = StateMachines::Machine.new(@model, :status, :initial => :parked)
12
+ @machine.state :parked, :value => 1
13
+ @record = @model.new
14
+ end
15
+
16
+ def test_should_use_machine_default
17
+ assert_equal 1, @record.status
18
+ end
19
+
20
+ def test_should_generate_a_warning
21
+ assert_match(/Both Foo and its :status machine have defined a different default for "status". Use only one or the other for defining defaults to avoid unexpected behaviors\./, $stderr.string)
22
+ end
23
+
24
+ def teardown
25
+ $stderr = @original_stderr
26
+ super
27
+ end
28
+ end
29
+
@@ -0,0 +1,24 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDirtyAttributeAndCustomAttributesDuringLoopbackTest < BaseTestCase
4
+ def setup
5
+ @model = new_model do
6
+ connection.add_column table_name, :status, :string
7
+ end
8
+ @machine = StateMachines::Machine.new(@model, :status, :initial => :parked)
9
+ @machine.event :park
10
+
11
+ @record = @model.create
12
+
13
+ @transition = StateMachines::Transition.new(@record, @machine, :park, :parked, :parked)
14
+ @transition.perform(false)
15
+ end
16
+
17
+ def test_should_not_include_state_in_changed_attributes
18
+ assert_equal [], @record.changed
19
+ end
20
+
21
+ def test_should_not_track_attribute_changes
22
+ assert_equal nil, @record.changes['status']
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDirtyAttributeAndStateEventsTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model, :initial => :parked)
7
+ @machine.event :ignite
8
+
9
+ @record = @model.create
10
+ @record.state_event = 'ignite'
11
+ end
12
+
13
+ def test_should_not_include_state_in_changed_attributes
14
+ assert_equal [], @record.changed
15
+ end
16
+
17
+ def test_should_not_track_attribute_change
18
+ assert_equal nil, @record.changes['state']
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDirtyAttributesAndCustomAttributeTest < BaseTestCase
4
+ def setup
5
+ @model = new_model do
6
+ connection.add_column table_name, :status, :string
7
+ end
8
+ @machine = StateMachines::Machine.new(@model, :status, :initial => :parked)
9
+ @machine.event :ignite
10
+ @machine.state :idling
11
+
12
+ @record = @model.create
13
+
14
+ @transition = StateMachines::Transition.new(@record, @machine, :ignite, :parked, :idling)
15
+ @transition.perform(false)
16
+ end
17
+
18
+ def test_should_include_state_in_changed_attributes
19
+ assert_equal %w(status), @record.changed
20
+ end
21
+
22
+ def test_should_track_attribute_change
23
+ assert_equal %w(parked idling), @record.changes['status']
24
+ end
25
+
26
+ def test_should_not_reset_changes_on_multiple_transitions
27
+ transition = StateMachines::Transition.new(@record, @machine, :ignite, :idling, :idling)
28
+ transition.perform(false)
29
+
30
+ assert_equal %w(parked idling), @record.changes['status']
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDirtyAttributesDuringLoopbackTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model, :initial => :parked)
7
+ @machine.event :park
8
+
9
+ @record = @model.create
10
+
11
+ @transition = StateMachines::Transition.new(@record, @machine, :park, :parked, :parked)
12
+ @transition.perform(false)
13
+ end
14
+
15
+ def test_should_not_include_state_in_changed_attributes
16
+ assert_equal [], @record.changed
17
+ end
18
+
19
+ def test_should_not_track_attribute_changes
20
+ assert_equal nil, @record.changes['state']
21
+ end
22
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDirtyAttributesTest < BaseTestCase
4
+ def setup
5
+ @model = new_model
6
+ @machine = StateMachines::Machine.new(@model, :initial => :parked)
7
+ @machine.event :ignite
8
+ @machine.state :idling
9
+
10
+ @record = @model.create
11
+
12
+ @transition = StateMachines::Transition.new(@record, @machine, :ignite, :parked, :idling)
13
+ @transition.perform(false)
14
+ end
15
+
16
+ def test_should_include_state_in_changed_attributes
17
+ assert_equal %w(state), @record.changed
18
+ end
19
+
20
+ def test_should_track_attribute_change
21
+ assert_equal %w(parked idling), @record.changes['state']
22
+ end
23
+
24
+ def test_should_not_reset_changes_on_multiple_transitions
25
+ transition = StateMachines::Transition.new(@record, @machine, :ignite, :idling, :idling)
26
+ transition.perform(false)
27
+
28
+ assert_equal %w(parked idling), @record.changes['state']
29
+ end
30
+
31
+ def test_should_not_have_changes_when_loaded_from_database
32
+ record = @model.find(@record.id)
33
+ refute record.changed?
34
+ end
35
+ end
@@ -0,0 +1,99 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithDynamicInitialStateTest < BaseTestCase
4
+ def setup
5
+ @model = new_model do
6
+ attr_accessor :value
7
+ end
8
+ @machine = StateMachines::Machine.new(@model, :initial => lambda { |object| :parked })
9
+ @machine.state :parked
10
+ end
11
+
12
+ def test_should_set_initial_state_on_created_object
13
+ record = @model.new
14
+ assert_equal 'parked', record.state
15
+ end
16
+
17
+ def test_should_still_set_attributes
18
+ record = @model.new(:value => 1)
19
+ assert_equal 1, record.value
20
+ end
21
+
22
+ def test_should_still_allow_initialize_blocks
23
+ block_args = nil
24
+ record = @model.new do |*args|
25
+ block_args = args
26
+ end
27
+
28
+ assert_equal [record], block_args
29
+ end
30
+
31
+ def test_should_set_attributes_prior_to_initialize_block
32
+ state = nil
33
+ @model.new do |record|
34
+ state = record.state
35
+ end
36
+
37
+ assert_equal 'parked', state
38
+ end
39
+
40
+ def test_should_set_attributes_prior_to_after_initialize_hook
41
+ state = nil
42
+ @model.after_initialize do |record|
43
+ state = record.state
44
+ end
45
+ @model.new
46
+ assert_equal 'parked', state
47
+ end
48
+
49
+ def test_should_set_initial_state_after_setting_attributes
50
+ @model.class_eval do
51
+ attr_accessor :state_during_setter
52
+
53
+ remove_method :value=
54
+ define_method(:value=) do |value|
55
+ self.state_during_setter = state || 'nil'
56
+ end
57
+ end
58
+
59
+ record = @model.new(:value => 1)
60
+ assert_equal 'nil', record.state_during_setter
61
+ end
62
+
63
+ def test_should_not_set_initial_state_after_already_initialized
64
+ record = @model.new(:value => 1)
65
+ assert_equal 'parked', record.state
66
+
67
+ record.state = 'idling'
68
+ record.attributes = {}
69
+ assert_equal 'idling', record.state
70
+ end
71
+
72
+ def test_should_persist_initial_state
73
+ record = @model.new
74
+ record.save
75
+ record.reload
76
+ assert_equal 'parked', record.state
77
+ end
78
+
79
+ def test_should_persist_initial_state_on_dup
80
+ record = @model.create.dup
81
+ record.save
82
+ record.reload
83
+ assert_equal 'parked', record.state
84
+ end
85
+
86
+ def test_should_use_stored_values_when_loading_from_database
87
+ @machine.state :idling
88
+
89
+ record = @model.find(@model.create(:state => 'idling').id)
90
+ assert_equal 'idling', record.state
91
+ end
92
+
93
+ def test_should_use_stored_values_when_loading_from_database_with_nil_state
94
+ @machine.state nil
95
+
96
+ record = @model.find(@model.create(:state => nil).id)
97
+ assert_nil record.state
98
+ end
99
+ end
@@ -0,0 +1,48 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MachineWithEventAttributesOnAutosaveTest < BaseTestCase
4
+ def setup
5
+ @vehicle_model = new_model(:vehicle) do
6
+ connection.add_column table_name, :owner_id, :integer
7
+ end
8
+ MachineWithEventAttributesOnAutosaveTest.const_set('Vehicle', @vehicle_model)
9
+
10
+ @owner_model = new_model(:owner)
11
+ MachineWithEventAttributesOnAutosaveTest.const_set('Owner', @owner_model)
12
+
13
+ machine = StateMachines::Machine.new(@vehicle_model)
14
+ machine.event :ignite do
15
+ transition :parked => :idling
16
+ end
17
+
18
+ @owner = @owner_model.create
19
+ @vehicle = @vehicle_model.create(:state => 'parked', :owner_id => @owner.id)
20
+ end
21
+
22
+ def test_should_persist_has_one_autosave
23
+ @owner_model.has_one :vehicle, :class_name => 'MachineWithEventAttributesOnAutosaveTest::Vehicle', :autosave => true
24
+ @owner.vehicle.state_event = 'ignite'
25
+ @owner.save
26
+
27
+ @vehicle.reload
28
+ assert_equal 'idling', @vehicle.state
29
+ end
30
+
31
+ def test_should_persist_has_many_autosave
32
+ @owner_model.has_many :vehicles, :class_name => 'MachineWithEventAttributesOnAutosaveTest::Vehicle', :autosave => true
33
+ @owner.vehicles[0].state_event = 'ignite'
34
+ @owner.save
35
+
36
+ @vehicle.reload
37
+ assert_equal 'idling', @vehicle.state
38
+ end
39
+
40
+ def teardown
41
+ MachineWithEventAttributesOnAutosaveTest.class_eval do
42
+ remove_const('Vehicle')
43
+ remove_const('Owner')
44
+ end
45
+ ActiveSupport::Dependencies.clear if defined?(ActiveSupport::Dependencies)
46
+ super
47
+ end
48
+ end