transitions 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -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