transitions 0.0.8 → 0.0.9

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.
@@ -0,0 +1,3 @@
1
+ pkg
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ transitions (0.0.9)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ activemodel (3.0.0)
10
+ activesupport (= 3.0.0)
11
+ builder (~> 2.1.2)
12
+ i18n (~> 0.4.1)
13
+ activerecord (3.0.0)
14
+ activemodel (= 3.0.0)
15
+ activesupport (= 3.0.0)
16
+ arel (~> 1.0.0)
17
+ tzinfo (~> 0.3.23)
18
+ activesupport (3.0.0)
19
+ arel (1.0.1)
20
+ activesupport (~> 3.0.0)
21
+ builder (2.1.2)
22
+ i18n (0.4.1)
23
+ mocha (0.9.8)
24
+ rake
25
+ rake (0.8.7)
26
+ sqlite3-ruby (1.3.1)
27
+ test-unit (2.1.1)
28
+ tzinfo (0.3.23)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ activerecord (~> 3)
35
+ bundler (~> 1)
36
+ mocha
37
+ sqlite3-ruby
38
+ test-unit (~> 2)
39
+ transitions!
@@ -10,16 +10,16 @@ If you're using Rails + ActiveRecord + Bundler
10
10
 
11
11
  # in your Gemfile
12
12
  gem "transitions", :require => ["transitions", "active_record/transitions"]
13
-
13
+
14
14
  # in your AR models that will use the state machine
15
15
  include ::Transitions
16
16
  include ActiveRecord::Transitions
17
-
17
+
18
18
  state_machine do
19
19
  state :available # first one is initial state
20
20
  state :out_of_stock
21
21
  state :discontinue
22
-
22
+
23
23
  event :discontinue do
24
24
  transitions :to => :discontinue, :from => [:available, :out_of_stock], :on_transition => :do_discontinue
25
25
  end
@@ -31,6 +31,12 @@ If you're using Rails + ActiveRecord + Bundler
31
31
  end
32
32
  end
33
33
 
34
+ == Usage
35
+
36
+ Krzysiek Heród (aka {Netizer}[http://github.com/netizer]) wrote a nice {blog
37
+ post}[http://dev.netizer.pl/transitions-state-machine-for-rails-3.html]
38
+ about using Transitions in ActiveRecord.
39
+
34
40
  == Copyright
35
41
 
36
42
  Copyright (c) 2010 Jakub Kuźma. See LICENSE for details.
@@ -0,0 +1,12 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+ Bundler.setup
4
+
5
+ require "rake/testtask"
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << "lib" << "test"
8
+ test.pattern = "test/**/test_*.rb"
9
+ test.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -1,3 +1,3 @@
1
1
  module Transitions
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -0,0 +1,14 @@
1
+ Bundler.require
2
+ require "test/unit"
3
+ require "active_support/all"
4
+ require "active_record"
5
+ require "mocha"
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require "transitions"
10
+ require "active_record/transitions"
11
+
12
+ class Test::Unit::TestCase
13
+
14
+ end
@@ -0,0 +1,112 @@
1
+ require "helper"
2
+ require 'active_support/core_ext/module/aliasing'
3
+
4
+ class CreateTrafficLights < ActiveRecord::Migration
5
+ def self.up
6
+ create_table(:traffic_lights) { |t| t.string :state }
7
+ end
8
+ end
9
+
10
+ class TrafficLight < ActiveRecord::Base
11
+ include ActiveRecord::Transitions
12
+
13
+ state_machine do
14
+ state :off
15
+
16
+ state :red
17
+ state :green
18
+ state :yellow
19
+
20
+ event :red_on do
21
+ transitions :to => :red, :from => [:yellow]
22
+ end
23
+
24
+ event :green_on do
25
+ transitions :to => :green, :from => [:red]
26
+ end
27
+
28
+ event :yellow_on do
29
+ transitions :to => :yellow, :from => [:green]
30
+ end
31
+
32
+ event :reset do
33
+ transitions :to => :red, :from => [:off]
34
+ end
35
+ end
36
+ end
37
+
38
+ class ProtectedTrafficLight < TrafficLight
39
+ attr_protected :state
40
+ end
41
+
42
+ class ValidatingTrafficLight < TrafficLight
43
+ validate {|t| errors.add(:base, 'This TrafficLight will never validate after creation') unless t.new_record? }
44
+ end
45
+
46
+ class TestActiveRecord < Test::Unit::TestCase
47
+ def setup
48
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
49
+ ActiveRecord::Migration.verbose = false
50
+ CreateTrafficLights.migrate(:up)
51
+
52
+ @light = TrafficLight.create!
53
+ end
54
+
55
+ test "states initial state" do
56
+ assert @light.off?
57
+ assert_equal :off, @light.current_state
58
+ end
59
+
60
+ test "transition to a valid state" do
61
+ @light.reset
62
+ assert @light.red?
63
+ assert_equal :red, @light.current_state
64
+
65
+ @light.green_on
66
+ assert @light.green?
67
+ assert_equal :green, @light.current_state
68
+ end
69
+
70
+ test "transition does not persist state" do
71
+ @light.reset
72
+ assert_equal :red, @light.current_state
73
+ @light.reload
74
+ assert_equal "off", @light.state
75
+ end
76
+
77
+ test "transition does persists state" do
78
+ @light.reset!
79
+ assert_equal :red, @light.current_state
80
+ @light.reload
81
+ assert_equal "red", @light.state
82
+ end
83
+
84
+ test "transition to an invalid state" do
85
+ assert_raise(Transitions::InvalidTransition) { @light.yellow_on }
86
+ assert_equal :off, @light.current_state
87
+ end
88
+
89
+ test "transition does persists state when state is protected" do
90
+ protected_light = ProtectedTrafficLight.create!
91
+ protected_light.reset!
92
+ assert_equal :red, protected_light.current_state
93
+ protected_light.reload
94
+ assert_equal "red", protected_light.state
95
+ end
96
+
97
+ test "transition with wrong state will not validate" do
98
+ for s in @light.class.state_machine.states
99
+ @light.state = s.name
100
+ assert @light.valid?
101
+ end
102
+ @light.state = "invalid_one"
103
+ assert_false @light.valid?
104
+ end
105
+
106
+ test "transition raises exception when model validation fails" do
107
+ validating_light = ValidatingTrafficLight.create!
108
+ assert_raise(ActiveRecord::RecordInvalid) do
109
+ validating_light.reset!
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,28 @@
1
+ require "helper"
2
+
3
+ class TestEvent < Test::Unit::TestCase
4
+ def setup
5
+ @state_name = :close_order
6
+ @success = :success_callback
7
+ end
8
+
9
+ def new_event
10
+ @event = Transitions::Event.new(nil, @state_name, {:success => @success}) do
11
+ transitions :to => :closed, :from => [:open, :received]
12
+ end
13
+ end
14
+
15
+ test "should set the name" do
16
+ assert_equal @state_name, new_event.name
17
+ end
18
+
19
+ test "should set the success option" do
20
+ assert_equal @success, new_event.success
21
+ end
22
+
23
+ test "should create StateTransitions" do
24
+ Transitions::StateTransition.expects(:new).with(:to => :closed, :from => :open)
25
+ Transitions::StateTransition.expects(:new).with(:to => :closed, :from => :received)
26
+ new_event
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ require "helper"
2
+
3
+ class ArgumentsTestSubject
4
+ include Transitions
5
+ attr_accessor :date
6
+
7
+ state_machine do
8
+ state :initial
9
+ state :opened
10
+
11
+ event :open do
12
+ transitions :from => :initial, :to => :opened, :on_transition => :update_date
13
+ end
14
+ end
15
+
16
+ def update_date(date = Date.today)
17
+ self.date = date
18
+ end
19
+ end
20
+
21
+ class StateMachineMachineTest < Test::Unit::TestCase
22
+ test "pass arguments to transition method" do
23
+ subject = ArgumentsTestSubject.new
24
+ assert_equal :initial, subject.current_state
25
+ subject.open!(Date.yesterday)
26
+ assert_equal :opened, subject.current_state
27
+ assert_equal Date.yesterday, subject.date
28
+ end
29
+ end
30
+
@@ -0,0 +1,22 @@
1
+ require "helper"
2
+
3
+ class TestEventBeingFired < Test::Unit::TestCase
4
+ test "should raise an Transitions::InvalidTransition error if the transitions are empty" do
5
+ event = Transitions::Event.new(nil, :event)
6
+
7
+ assert_raise Transitions::InvalidTransition do
8
+ event.fire(nil)
9
+ end
10
+ end
11
+
12
+ test "should return the state of the first matching transition it finds" do
13
+ event = Transitions::Event.new(nil, :event) do
14
+ transitions :to => :closed, :from => [:open, :received]
15
+ end
16
+
17
+ obj = stub
18
+ obj.stubs(:current_state).returns(:open)
19
+
20
+ assert_equal :closed, event.fire(obj)
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ require "helper"
2
+
3
+ class MachineTestSubject
4
+ include Transitions
5
+
6
+ state_machine do
7
+ state :open
8
+ state :closed
9
+ end
10
+
11
+ state_machine :initial => :foo do
12
+ event :shutdown do
13
+ transitions :from => :open, :to => :closed
14
+ end
15
+
16
+ event :timeout do
17
+ transitions :from => :open, :to => :closed
18
+ end
19
+ end
20
+
21
+ state_machine :extra, :initial => :bar do
22
+ end
23
+ end
24
+
25
+ class TransitionsMachineTest < Test::Unit::TestCase
26
+ test "allows reuse of existing machines" do
27
+ assert_equal 2, MachineTestSubject.state_machines.size
28
+ end
29
+
30
+ test "sets #initial_state from :initial option" do
31
+ assert_equal :bar, MachineTestSubject.state_machine(:extra).initial_state
32
+ end
33
+
34
+ test "accesses non-default state machine" do
35
+ assert_kind_of Transitions::Machine, MachineTestSubject.state_machine(:extra)
36
+ end
37
+
38
+ test "finds events for given state" do
39
+ events = MachineTestSubject.state_machine.events_for(:open)
40
+ assert events.include?(:shutdown)
41
+ assert events.include?(:timeout)
42
+ end
43
+ end
@@ -0,0 +1,72 @@
1
+ require "helper"
2
+
3
+ class StateTestSubject
4
+ include Transitions
5
+
6
+ state_machine do
7
+ end
8
+ end
9
+
10
+ class TestState < Test::Unit::TestCase
11
+ def setup
12
+ @state_name = :astate
13
+ @machine = StateTestSubject.state_machine
14
+ @options = { :crazy_custom_key => "key", :machine => @machine }
15
+ end
16
+
17
+ def new_state(options={})
18
+ Transitions::State.new(@state_name, @options.merge(options))
19
+ end
20
+
21
+ test "sets the name" do
22
+ assert_equal :astate, new_state.name
23
+ end
24
+
25
+ test "sets the display_name from name" do
26
+ assert_equal "Astate", new_state.display_name
27
+ end
28
+
29
+ test "sets the display_name from options" do
30
+ assert_equal "A State", new_state(:display => "A State").display_name
31
+ end
32
+
33
+ test "sets the options and expose them as options" do
34
+ @options.delete(:machine)
35
+ assert_equal @options, new_state.options
36
+ end
37
+
38
+ test "equals a symbol of the same name" do
39
+ assert_equal new_state, :astate
40
+ end
41
+
42
+ test "equals a State of the same name" do
43
+ assert_equal new_state, new_state
44
+ end
45
+
46
+ test "should send a message to the record for an action if the action is present as a symbol" do
47
+ state = new_state(:entering => :foo)
48
+
49
+ record = stub
50
+ record.expects(:foo)
51
+
52
+ state.call_action(:entering, record)
53
+ end
54
+
55
+ test "should send a message to the record for an action if the action is present as a string" do
56
+ state = new_state(:entering => "foo")
57
+
58
+ record = stub
59
+ record.expects(:foo)
60
+
61
+ state.call_action(:entering, record)
62
+ end
63
+
64
+ test "should call a proc, passing in the record for an action if the action is present" do
65
+ state = new_state(:entering => Proc.new {|r| r.foobar})
66
+
67
+ record = stub
68
+ record.expects(:foobar)
69
+
70
+ state.call_action(:entering, record)
71
+ end
72
+ end
@@ -0,0 +1,45 @@
1
+ require "helper"
2
+
3
+ class TestStateTransition < Test::Unit::TestCase
4
+ test "should set from, to, and opts attr readers" do
5
+ opts = {:from => "foo", :to => "bar", :guard => "g"}
6
+ st = Transitions::StateTransition.new(opts)
7
+
8
+ assert_equal opts[:from], st.from
9
+ assert_equal opts[:to], st.to
10
+ assert_equal opts, st.options
11
+ end
12
+
13
+ test "should pass equality check if from and to are the same" do
14
+ opts = {:from => "foo", :to => "bar", :guard => "g"}
15
+ st = Transitions::StateTransition.new(opts)
16
+
17
+ obj = stub
18
+ obj.stubs(:from).returns(opts[:from])
19
+ obj.stubs(:to).returns(opts[:to])
20
+
21
+ assert_equal st, obj
22
+ end
23
+
24
+ test "should fail equality check if from are not the same" do
25
+ opts = {:from => "foo", :to => "bar", :guard => "g"}
26
+ st = Transitions::StateTransition.new(opts)
27
+
28
+ obj = stub
29
+ obj.stubs(:from).returns("blah")
30
+ obj.stubs(:to).returns(opts[:to])
31
+
32
+ assert_not_equal st, obj
33
+ end
34
+
35
+ test "should fail equality check if to are not the same" do
36
+ opts = {:from => "foo", :to => "bar", :guard => "g"}
37
+ st = Transitions::StateTransition.new(opts)
38
+
39
+ obj = stub
40
+ obj.stubs(:from).returns(opts[:from])
41
+ obj.stubs(:to).returns("blah")
42
+
43
+ assert_not_equal st, obj
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ require "helper"
2
+
3
+ class TestStateTransitionGuardCheck < Test::Unit::TestCase
4
+ test "should return true of there is no guard" do
5
+ opts = {:from => "foo", :to => "bar"}
6
+ st = Transitions::StateTransition.new(opts)
7
+
8
+ assert st.perform(nil)
9
+ end
10
+
11
+ test "should call the method on the object if guard is a symbol" do
12
+ opts = {:from => "foo", :to => "bar", :guard => :test_guard}
13
+ st = Transitions::StateTransition.new(opts)
14
+
15
+ obj = stub
16
+ obj.expects(:test_guard)
17
+
18
+ st.perform(obj)
19
+ end
20
+
21
+ test "should call the method on the object if guard is a string" do
22
+ opts = {:from => "foo", :to => "bar", :guard => "test_guard"}
23
+ st = Transitions::StateTransition.new(opts)
24
+
25
+ obj = stub
26
+ obj.expects(:test_guard)
27
+
28
+ st.perform(obj)
29
+ end
30
+
31
+ test "should call the proc passing the object if the guard is a proc" do
32
+ opts = {:from => "foo", :to => "bar", :guard => Proc.new {|o| o.test_guard}}
33
+ st = Transitions::StateTransition.new(opts)
34
+
35
+ obj = stub
36
+ obj.expects(:test_guard)
37
+
38
+ st.perform(obj)
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/transitions/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "transitions"
6
+ s.version = Transitions::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Jakub Kuźma"]
9
+ s.email = "qoobaa@gmail.com"
10
+ s.homepage = "http://github.com/qoobaa/transitions"
11
+ s.summary = "State machine extracted from ActiveModel"
12
+ s.description = "Lightweight state machine extracted from ActiveModel"
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "transitions"
16
+
17
+ s.add_development_dependency "bundler", "~> 1"
18
+ s.add_development_dependency "test-unit", "~> 2"
19
+ s.add_development_dependency "mocha"
20
+ s.add_development_dependency "sqlite3-ruby"
21
+ s.add_development_dependency "activerecord", "~> 3"
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
25
+ s.require_path = 'lib'
26
+ end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: transitions
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 0
9
- - 8
10
- version: 0.0.8
8
+ - 9
9
+ version: 0.0.9
11
10
  platform: ruby
12
11
  authors:
13
12
  - "Jakub Ku\xC5\xBAma"
@@ -15,66 +14,74 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-08-12 00:00:00 +02:00
17
+ date: 2010-09-21 00:00:00 +02:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
- name: test-unit
23
- prerelease: false
21
+ name: bundler
24
22
  requirement: &id001 !ruby/object:Gem::Requirement
25
23
  none: false
26
24
  requirements:
27
- - - ">="
25
+ - - ~>
28
26
  - !ruby/object:Gem::Version
29
- hash: 3
30
27
  segments:
31
- - 2
32
- - 0
33
- version: "2.0"
28
+ - 1
29
+ version: "1"
34
30
  type: :development
31
+ prerelease: false
35
32
  version_requirements: *id001
36
33
  - !ruby/object:Gem::Dependency
37
- name: mocha
38
- prerelease: false
34
+ name: test-unit
39
35
  requirement: &id002 !ruby/object:Gem::Requirement
40
36
  none: false
41
37
  requirements:
42
- - - ">="
38
+ - - ~>
43
39
  - !ruby/object:Gem::Version
44
- hash: 3
45
40
  segments:
46
- - 0
47
- version: "0"
41
+ - 2
42
+ version: "2"
48
43
  type: :development
44
+ prerelease: false
49
45
  version_requirements: *id002
50
46
  - !ruby/object:Gem::Dependency
51
- name: sqlite3-ruby
52
- prerelease: false
47
+ name: mocha
53
48
  requirement: &id003 !ruby/object:Gem::Requirement
54
49
  none: false
55
50
  requirements:
56
51
  - - ">="
57
52
  - !ruby/object:Gem::Version
58
- hash: 3
59
53
  segments:
60
54
  - 0
61
55
  version: "0"
62
56
  type: :development
57
+ prerelease: false
63
58
  version_requirements: *id003
64
59
  - !ruby/object:Gem::Dependency
65
- name: activerecord
66
- prerelease: false
60
+ name: sqlite3-ruby
67
61
  requirement: &id004 !ruby/object:Gem::Requirement
68
62
  none: false
69
63
  requirements:
70
64
  - - ">="
71
65
  - !ruby/object:Gem::Version
72
- hash: 3
73
66
  segments:
74
67
  - 0
75
68
  version: "0"
76
69
  type: :development
70
+ prerelease: false
77
71
  version_requirements: *id004
72
+ - !ruby/object:Gem::Dependency
73
+ name: activerecord
74
+ requirement: &id005 !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ segments:
80
+ - 3
81
+ version: "3"
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: *id005
78
85
  description: Lightweight state machine extracted from ActiveModel
79
86
  email: qoobaa@gmail.com
80
87
  executables: []
@@ -84,15 +91,29 @@ extensions: []
84
91
  extra_rdoc_files: []
85
92
 
86
93
  files:
94
+ - .gitignore
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - LICENSE
98
+ - README.rdoc
99
+ - Rakefile
100
+ - lib/active_record/transitions.rb
87
101
  - lib/transitions.rb
88
- - lib/transitions/state_transition.rb
89
- - lib/transitions/state.rb
90
102
  - lib/transitions/event.rb
91
- - lib/transitions/version.rb
92
103
  - lib/transitions/machine.rb
93
- - lib/active_record/transitions.rb
94
- - LICENSE
95
- - README.rdoc
104
+ - lib/transitions/state.rb
105
+ - lib/transitions/state_transition.rb
106
+ - lib/transitions/version.rb
107
+ - test/helper.rb
108
+ - test/test_active_record.rb
109
+ - test/test_event.rb
110
+ - test/test_event_arguments.rb
111
+ - test/test_event_being_fired.rb
112
+ - test/test_machine.rb
113
+ - test/test_state.rb
114
+ - test/test_state_transition.rb
115
+ - test/test_state_transition_guard_check.rb
116
+ - transitions.gemspec
96
117
  has_rdoc: true
97
118
  homepage: http://github.com/qoobaa/transitions
98
119
  licenses: []
@@ -107,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
128
  requirements:
108
129
  - - ">="
109
130
  - !ruby/object:Gem::Version
110
- hash: 3
131
+ hash: -568409294339076591
111
132
  segments:
112
133
  - 0
113
134
  version: "0"
@@ -116,7 +137,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
137
  requirements:
117
138
  - - ">="
118
139
  - !ruby/object:Gem::Version
119
- hash: 23
120
140
  segments:
121
141
  - 1
122
142
  - 3
@@ -124,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
144
  version: 1.3.6
125
145
  requirements: []
126
146
 
127
- rubyforge_project:
147
+ rubyforge_project: transitions
128
148
  rubygems_version: 1.3.7
129
149
  signing_key:
130
150
  specification_version: 3