transitions 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/.travis.yml +3 -1
- data/CHANGELOG.md +4 -0
- data/Gemfile +7 -2
- data/README.md +1 -1
- data/Rakefile +4 -4
- data/lib/active_model/transitions.rb +8 -8
- data/lib/transitions/event.rb +15 -16
- data/lib/transitions/machine.rb +4 -5
- data/lib/transitions/presenter.rb +1 -1
- data/lib/transitions/state.rb +2 -1
- data/lib/transitions/state_transition.rb +2 -2
- data/lib/transitions/version.rb +1 -1
- data/lib/transitions.rb +10 -8
- data/test/active_record/test_active_record.rb +64 -66
- data/test/active_record/test_active_record_scopes.rb +7 -7
- data/test/active_record/test_active_record_timestamps.rb +27 -28
- data/test/active_record/test_custom_select.rb +3 -3
- data/test/event/test_event.rb +20 -20
- data/test/event/test_event_arguments.rb +3 -4
- data/test/event/test_event_being_fired.rb +4 -4
- data/test/event/test_event_checks.rb +5 -6
- data/test/helper.rb +1 -1
- data/test/machine/machine_template.rb +4 -4
- data/test/machine/test_available_states_listing.rb +1 -1
- data/test/machine/test_fire_event_machine.rb +5 -5
- data/test/machine/test_machine.rb +10 -10
- data/test/state/test_state.rb +16 -16
- data/test/state/test_state_predicate_method.rb +2 -2
- data/test/state_transition/test_state_transition.rb +11 -11
- data/test/state_transition/test_state_transition_event_failed_callback.rb +3 -3
- data/test/state_transition/test_state_transition_event_fired_callback.rb +3 -3
- data/test/state_transition/test_state_transition_guard_check.rb +14 -15
- data/test/state_transition/test_state_transition_on_transition_callback.rb +4 -4
- data/test/state_transition/test_state_transition_success_callback.rb +8 -8
- data/transitions.gemspec +16 -16
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50aa94816f542aa2e3ddfb4ea2c3b158e1302226
|
4
|
+
data.tar.gz: e9f190796c29fc615582e3722c0d42fabaadb84b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3428e39ec7f594f3e2988be6d99438b52fff0eed9b92e668c49a98d6107824c0aadd4ac4cbade09d609bfb3738a7f045f5223ae89a938d8e6982bc440935a888
|
7
|
+
data.tar.gz: 2878d1c45b68664d87bc1b036ef7d25cb4caaf01e8ebd9bdcc9e6130476c5d0aac0088ae7255a4ddb1591c27bb17fbce2938f0eab088afbd5ae153d1e61ef17e
|
data/.rubocop.yml
ADDED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -3,5 +3,10 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
gem 'activerecord', '~> 3.2.14'
|
6
|
-
gem 'activerecord-jdbcsqlite3-adapter', :
|
7
|
-
|
6
|
+
gem 'activerecord-jdbcsqlite3-adapter', platforms: :jruby
|
7
|
+
|
8
|
+
platforms :ruby do
|
9
|
+
gem 'sqlite3'
|
10
|
+
gem 'pry'
|
11
|
+
gem 'byebug'
|
12
|
+
end
|
data/README.md
CHANGED
@@ -215,7 +215,7 @@ can use `success`. This will be called after the `save!` is complete (if you
|
|
215
215
|
use the `state_name!` method) and should be used for any methods that require
|
216
216
|
that the object be persisted.
|
217
217
|
```ruby
|
218
|
-
event :discontinue, :success => :
|
218
|
+
event :discontinue, :success => :notify_admin do
|
219
219
|
transitions :to => :discontinued, :from => [:available, :out_of_stock]
|
220
220
|
end
|
221
221
|
```
|
data/Rakefile
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
Bundler.setup
|
4
4
|
|
5
5
|
require 'appraisal'
|
6
6
|
|
7
|
-
require
|
7
|
+
require 'rake/testtask'
|
8
8
|
Rake::TestTask.new(:test) do |test|
|
9
9
|
test.libs = %w(lib test)
|
10
|
-
test.pattern =
|
10
|
+
test.pattern = 'test/**/test_*.rb'
|
11
11
|
test.verbose = true
|
12
12
|
end
|
13
13
|
|
14
|
-
task :
|
14
|
+
task default: :test
|
@@ -6,8 +6,8 @@ module ActiveModel
|
|
6
6
|
class ::Transitions::Machine
|
7
7
|
unless method_defined?(:new_transitions_initialize) || method_defined?(:new_transitions_update)
|
8
8
|
attr_reader :attribute_name
|
9
|
-
|
10
|
-
|
9
|
+
alias_method :old_transitions_initialize, :initialize
|
10
|
+
alias_method :old_transitions_update, :update
|
11
11
|
|
12
12
|
def new_transitions_initialize(*args, &block)
|
13
13
|
@attribute_name = :state
|
@@ -19,8 +19,8 @@ module ActiveModel
|
|
19
19
|
old_transitions_update(options, &block)
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
alias_method :initialize, :new_transitions_initialize
|
23
|
+
alias_method :update, :new_transitions_update
|
24
24
|
end
|
25
25
|
end
|
26
26
|
include ::Transitions
|
@@ -66,7 +66,7 @@ module ActiveModel
|
|
66
66
|
|
67
67
|
def set_initial_state
|
68
68
|
# In case we use a query with a custom select that excludes our state attribute name we need to skip the initialization below.
|
69
|
-
if self.
|
69
|
+
if self.attribute_names.include?(transitions_state_column_name.to_s) && state_not_set?
|
70
70
|
self[transitions_state_column_name] = self.class.get_state_machine.initial_state.to_s
|
71
71
|
self.class.get_state_machine.state_index[self[transitions_state_column_name].to_sym].call_action(:enter, self)
|
72
72
|
end
|
@@ -74,13 +74,13 @@ module ActiveModel
|
|
74
74
|
|
75
75
|
def state_presence
|
76
76
|
unless self[transitions_state_column_name].present?
|
77
|
-
|
77
|
+
errors.add(transitions_state_column_name, :presence)
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
def state_inclusion
|
82
|
-
unless self.class.get_state_machine.states.map{|s| s.name.to_s }.include?(self[transitions_state_column_name].to_s)
|
83
|
-
|
82
|
+
unless self.class.get_state_machine.states.map { |s| s.name.to_s }.include?(self[transitions_state_column_name].to_s)
|
83
|
+
errors.add(transitions_state_column_name, :inclusion, value: self[transitions_state_column_name])
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
data/lib/transitions/event.rb
CHANGED
@@ -13,15 +13,15 @@ module Transitions
|
|
13
13
|
machine.fire_event(name, self, false, *args)
|
14
14
|
end
|
15
15
|
|
16
|
-
machine.klass.send(:define_method, "can_#{name
|
16
|
+
machine.klass.send(:define_method, "can_#{name}?") do |*_args|
|
17
17
|
machine.events_for(current_state).include?(name.to_sym)
|
18
18
|
end
|
19
19
|
|
20
|
-
machine.klass.send(:define_method, "can_execute_#{name
|
20
|
+
machine.klass.send(:define_method, "can_execute_#{name}?") do |*args|
|
21
21
|
event = name.to_sym
|
22
22
|
|
23
|
-
send("can_#{name
|
24
|
-
|
23
|
+
send("can_#{name}?", *args) &&
|
24
|
+
machine.events[event].can_execute_transition_from_state?(current_state, self, *args)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
update(options, &block)
|
@@ -29,7 +29,7 @@ module Transitions
|
|
29
29
|
|
30
30
|
def fire(obj, to_state = nil, *args)
|
31
31
|
transitions = @transitions.select { |t| t.from == obj.current_state }
|
32
|
-
|
32
|
+
fail InvalidTransition, error_message_for_invalid_transitions(obj) if transitions.size == 0
|
33
33
|
|
34
34
|
next_state = nil
|
35
35
|
transitions.each do |transition|
|
@@ -60,7 +60,7 @@ module Transitions
|
|
60
60
|
name == event.name
|
61
61
|
end
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
# Has the timestamp option been specified for this event?
|
65
65
|
def timestamp_defined?
|
66
66
|
!@timestamp.nil?
|
@@ -72,12 +72,12 @@ module Transitions
|
|
72
72
|
instance_eval(&block) if block
|
73
73
|
self
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
# update the timestamp attribute on obj
|
77
77
|
def update_event_timestamp(obj, next_state)
|
78
78
|
obj.send "#{timestamp_attribute_name(obj, next_state)}=", Time.now
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
# Set the timestamp attribute.
|
82
82
|
# @raise [ArgumentError] timestamp should be either a String, Symbol or true
|
83
83
|
def timestamp=(value)
|
@@ -85,36 +85,35 @@ module Transitions
|
|
85
85
|
when String, Symbol, TrueClass
|
86
86
|
@timestamp = value
|
87
87
|
else
|
88
|
-
|
88
|
+
fail ArgumentError, 'timestamp must be either: true, a String or a Symbol'
|
89
89
|
end
|
90
90
|
end
|
91
|
-
|
92
91
|
|
93
92
|
private
|
94
|
-
|
93
|
+
|
95
94
|
# Returns the name of the timestamp attribute for this event
|
96
95
|
# If the timestamp was simply true it returns the default_timestamp_name
|
97
96
|
# otherwise, returns the user-specified timestamp name
|
98
97
|
def timestamp_attribute_name(obj, next_state)
|
99
98
|
timestamp == true ? default_timestamp_name(obj, next_state) : @timestamp
|
100
99
|
end
|
101
|
-
|
100
|
+
|
102
101
|
# If @timestamp is true, try a default timestamp name
|
103
102
|
def default_timestamp_name(obj, next_state)
|
104
|
-
at_name =
|
105
|
-
on_name =
|
103
|
+
at_name = '%s_at' % next_state
|
104
|
+
on_name = '%s_on' % next_state
|
106
105
|
case
|
107
106
|
when obj.respond_to?(at_name) then at_name
|
108
107
|
when obj.respond_to?(on_name) then on_name
|
109
108
|
else
|
110
|
-
|
109
|
+
fail NoMethodError, "Couldn't find a suitable timestamp field for event: #{@name}.
|
111
110
|
Please define #{at_name} or #{on_name} in #{obj.class}"
|
112
111
|
end
|
113
112
|
end
|
114
113
|
|
115
114
|
def transitions(trans_opts)
|
116
115
|
Array(trans_opts[:from]).each do |s|
|
117
|
-
@transitions << StateTransition.new(trans_opts.merge(
|
116
|
+
@transitions << StateTransition.new(trans_opts.merge(from: s.to_sym))
|
118
117
|
end
|
119
118
|
end
|
120
119
|
|
data/lib/transitions/machine.rb
CHANGED
@@ -45,7 +45,7 @@ module Transitions
|
|
45
45
|
|
46
46
|
def events_for(state)
|
47
47
|
events = @events.values.select { |event| event.transitions_from_state?(state) }
|
48
|
-
events.map!
|
48
|
+
events.map!(&:name)
|
49
49
|
end
|
50
50
|
|
51
51
|
def current_state_variable
|
@@ -53,7 +53,7 @@ module Transitions
|
|
53
53
|
:@current_state
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
private
|
57
57
|
|
58
58
|
def handle_state_exit_callback(record)
|
59
59
|
state_index[record.current_state].call_action(:exit, record)
|
@@ -85,7 +85,7 @@ module Transitions
|
|
85
85
|
|
86
86
|
def state(name, options = {})
|
87
87
|
unless @state_index.key? name # Just ignore duplicates
|
88
|
-
state = State.new(name, :
|
88
|
+
state = State.new(name, machine: self)
|
89
89
|
state.update options
|
90
90
|
@state_index[name] = state
|
91
91
|
@states << state
|
@@ -100,11 +100,10 @@ module Transitions
|
|
100
100
|
@states.each do |state|
|
101
101
|
state_name = state.name.to_s
|
102
102
|
if @klass.respond_to?(state_name)
|
103
|
-
|
103
|
+
fail InvalidMethodOverride, "Transitions: Can not define scope `#{state_name}` because there is already an equally named method defined - either rename the existing method or the state."
|
104
104
|
end
|
105
105
|
@klass.scope state_name, -> { @klass.where(@klass.state_machine.attribute_name => state_name) }
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
|
-
|
data/lib/transitions/state.rb
CHANGED
@@ -43,10 +43,11 @@ module Transitions
|
|
43
43
|
end
|
44
44
|
|
45
45
|
private
|
46
|
+
|
46
47
|
def define_state_query_method(machine)
|
47
48
|
method_name, state_name = "#{@name}?", @name # Instance vars are out of scope when calling define_method below, so we use local variables.
|
48
49
|
if machine.klass.method_defined?(method_name.to_sym)
|
49
|
-
|
50
|
+
fail InvalidMethodOverride, "Transitions: Can not define method `#{method_name}` because it is already defined - either rename the existing method or the state."
|
50
51
|
end
|
51
52
|
machine.klass.send :define_method, method_name do
|
52
53
|
current_state.to_s == state_name.to_s
|
@@ -25,7 +25,7 @@ module Transitions
|
|
25
25
|
end
|
26
26
|
else
|
27
27
|
# TODO We probably should check for this in the constructor and not that late.
|
28
|
-
|
28
|
+
fail ArgumentError, "You can only pass a Symbol, a String, a Proc or an Array to 'on_transition' - got #{@on_transition.class}." unless @on_transition.nil?
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
@@ -37,7 +37,7 @@ module Transitions
|
|
37
37
|
@from == value
|
38
38
|
end
|
39
39
|
|
40
|
-
|
40
|
+
private
|
41
41
|
|
42
42
|
def perform_guard(obj, guard, *args)
|
43
43
|
if guard.respond_to?(:call)
|
data/lib/transitions/version.rb
CHANGED
data/lib/transitions.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
require 'transitions/event'
|
2
|
+
require 'transitions/machine'
|
3
|
+
require 'transitions/presenter'
|
4
|
+
require 'transitions/state'
|
5
|
+
require 'transitions/state_transition'
|
6
|
+
require 'transitions/version'
|
7
7
|
|
8
8
|
module Transitions
|
9
9
|
class InvalidTransition < StandardError; end
|
@@ -26,10 +26,12 @@ module Transitions
|
|
26
26
|
block ? @state_machine.update(options, &block) : @state_machine
|
27
27
|
end
|
28
28
|
|
29
|
-
def get_state_machine
|
29
|
+
def get_state_machine
|
30
|
+
@state_machine
|
31
|
+
end
|
30
32
|
|
31
33
|
def available_states
|
32
|
-
@state_machine.states.map(&:name).sort_by
|
34
|
+
@state_machine.states.map(&:name).sort_by(&:to_s)
|
33
35
|
end
|
34
36
|
|
35
37
|
def available_events
|