flojo 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
File without changes
data/MIT_LICENSE ADDED
@@ -0,0 +1,11 @@
1
+ LICENSE:
2
+
3
+ (The MIT License)
4
+
5
+ Copyright © 2010 Joey Adarkwah
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,11 @@
1
+ CHANGELOG
2
+ MIT_LICENSE
3
+ README.rdoc
4
+ Rakefile
5
+ flojo.gemspec
6
+ lib/flojo.rb
7
+ test/test_active_record.rb
8
+ test/test_db.sqlite3
9
+ test/test_helper.rb
10
+ test/test_poro.rb
11
+ Manifest
data/README.rdoc ADDED
@@ -0,0 +1,109 @@
1
+ = Flojo
2
+
3
+ Flojo is a simple ActiveRecord aware state machine module, but it will also work with any plain old ruby object.
4
+ When used within an ActiveRecord subclass, flojo events can automatically save a record after a transition.
5
+
6
+ After including the module in your class and configuring it with an event _event_, and a state _state_,
7
+ you can interact with instances of that class using the dynamically generated methods of the following form:
8
+
9
+ object.wf_event - Triggers event and invokes any applicable transitions
10
+ object.wf_event! - Behaves just like object.wf_event but will also persist object.
11
+ object.wf_state? - Returns true if the current workflow state is _state_.
12
+ object.wf_current_state - Returns the objects current state.
13
+
14
+ To avoid method name collisions with your classes, Flojo methods are usually prefixed with "wf_".
15
+
16
+ See test.rb, test_active_record.rb and test_helper.rb for concrete examples.
17
+
18
+ == Install
19
+
20
+ Simply require flojo.rb.
21
+ If you are using rails, copy flojo.rb to your project's <b>lib</b> folder.
22
+ Alternatively, install the gem with gem install flojo.
23
+
24
+ == Usage
25
+
26
+ require 'flojo'
27
+
28
+ class Baby
29
+ # Include the module
30
+ include Flojo
31
+
32
+ # configure the states. The first element represents the initial state
33
+ workflow_states [:asleep, :crying, :pooping, :chilling, :puking]
34
+
35
+ # configure your transitions. Using: transition :begin_state, :end_state
36
+ event :feed do
37
+ transition :crying, :chilling
38
+ transition :chilling, :pooping
39
+ end
40
+
41
+ event :rock do
42
+ transition :crying, :chilling
43
+ transition :chilling, :asleep
44
+ transition :asleep, :pooping
45
+ end
46
+
47
+ event :burp do
48
+ transition :crying, :chilling
49
+ transition :chilling, :puking
50
+ end
51
+
52
+ event :wake do
53
+ transition :asleep, :crying
54
+ end
55
+
56
+ event :spank do
57
+ # :any is a wildcard state and is only valid as a begin state.
58
+ transition :any, :crying
59
+ end
60
+
61
+ # event, enter state and exit state callbacks should take the form wf_on_event,
62
+ wf_on_enter_state and wf_on_exit_state and are only called if they are defined
63
+ def wf_on_spank
64
+ puts "Never spank a baby! Somebody dial 911!"
65
+ end
66
+
67
+ def wf_on_enter_chilling
68
+ puts "drool and fart"
69
+ end
70
+
71
+ def wf_on_exit_asleep
72
+ puts "waaaaah waaaaah waaaaaah"
73
+ end
74
+
75
+ # called only after an event yields a transition.
76
+ def wf_after_transition
77
+ puts "Send a tweet baby is alive and kicking"
78
+ end
79
+
80
+ # called only after an event triggers a save.
81
+ def wf_after_save
82
+ puts "Send a tweet saying baby was saved"
83
+ end
84
+
85
+ end
86
+
87
+
88
+ baby = Baby.new
89
+ baby.wf_asleep? #Should return true
90
+
91
+ baby.wf_wake
92
+ baby.wf_current_state #Should return :awake
93
+
94
+ == ActiveRecord specific details
95
+ If you want the current workflow state persisted, your table needs to have a string column named _wf_state_.
96
+ If your table has a _wf_last_event_ column, that column will store the most recent event triggered on the object.
97
+ The module will still work if the wf_state is absent but the workflow state will be transient.
98
+ When used within an ActiveRecord subclass, the "!" versions of the wf_event methods will -
99
+ trigger a record save immediately after transition.
100
+
101
+ eg:
102
+ baby.wf_feed - Will *not* trigger a save.
103
+ baby.wf_feed! - *Will* trigger a save.
104
+
105
+ == Copyright
106
+
107
+ Copyright (c) 2010 Joey Adarkwah
108
+
109
+
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('flojo', '0.5.0') do |p|
6
+ p.description = "ActiveRecord aware workflow (state machine) module that will also work with any plain old ruby object."
7
+ p.summary = "When used within an ActiveRecord subclass, flojo events can automatically save a record after a transition.
8
+
9
+ After including the module in your class and configuring it with an event _event_, and a state _state_, you can interact with instances of that class using the dynamically generated methods of the following form:
10
+
11
+ +object.wf_event+ - Triggers event and invokes any applicable transitions
12
+ +object.wf_event!+ - Behaves just like +object.wf_event+ but will also persist object.
13
+ +object.wf_state?+ - Returns true if the current workflow state is _state_.
14
+ +object.wf_current_state+ - Returns the objects current state."
15
+
16
+ p.url = "http://github.com/alternegro/flojo"
17
+ p.author = "Joey Adarkwah"
18
+ p.email = "alternegro @nospam@ me.com"
19
+ p.development_dependencies = []
20
+ end
data/flojo.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{flojo}
5
+ s.version = "0.5.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Joey Adarkwah"]
9
+ s.date = %q{2010-12-07}
10
+ s.description = %q{ActiveRecord aware workflow (state machine) module that will also work with any plain old ruby object.}
11
+ s.email = %q{alternegro @nospam@ me.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "README.rdoc", "lib/flojo.rb"]
13
+ s.files = ["CHANGELOG", "MIT_LICENSE", "README.rdoc", "Rakefile", "flojo.gemspec", "lib/flojo.rb", "test/test_active_record.rb", "test/test_db.sqlite3", "test/test_helper.rb", "test/test_poro.rb", "Manifest"]
14
+ s.homepage = %q{http://github.com/alternegro/flojo}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Flojo", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{flojo}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{When used within an ActiveRecord subclass, flojo events can automatically save a record after a transition. After including the module in your class and configuring it with an event _event_, and a state _state_, you can interact with instances of that class using the dynamically generated methods of the following form: +object.wf_event+ - Triggers event and invokes any applicable transitions +object.wf_event!+ - Behaves just like +object.wf_event+ but will also persist object. +object.wf_state?+ - Returns true if the current workflow state is _state_. +object.wf_current_state+ - Returns the objects current state.}
20
+ s.test_files = ["test/test_active_record.rb", "test/test_helper.rb", "test/test_poro.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ else
28
+ end
29
+ else
30
+ end
31
+ end
data/lib/flojo.rb ADDED
@@ -0,0 +1,91 @@
1
+ module Flojo
2
+ def Flojo.included(host)
3
+
4
+ host.class_eval do
5
+ attr_writer :wf_current_state
6
+ attr_accessor :_wf_current_event_transition_map, :wf_previous_state
7
+ protected :wf_current_state=, :_set_workflow_state
8
+
9
+ def wf_current_state
10
+ wf_current_state = @wf_current_state.nil? ? wf_initial_state : @wf_current_state
11
+ end
12
+
13
+ def wf_initial_state
14
+ st = self.respond_to?(:wf_state) ? (wf_state || self.class.wf_states[0]) : self.class.wf_states[0]
15
+ st.to_sym
16
+ end
17
+
18
+ def self.workflow_states(s)
19
+ @workflow_states = s.uniq
20
+ self.synthesize_state_query_methods
21
+ end
22
+
23
+ def self.wf_states
24
+ @workflow_states
25
+ end
26
+
27
+ def self.synthesize_state_query_methods
28
+ @workflow_states.each {|st| define_method("wf_#{st}?") { st.eql?(wf_current_state)}}
29
+ end
30
+
31
+ def self.valid_state(*states)
32
+ states.each {|st| return false if !@workflow_states.include?(st) && (st != :any)}
33
+ return true
34
+ end
35
+
36
+ end
37
+
38
+ host.class_eval("def self.transition(start_state, end_state); raise 'Invalid Transition State' unless self.valid_state(start_state, end_state); @wf_current_event_transition_map[start_state]=end_state; end")
39
+
40
+ host.class_eval do
41
+ def self.event(e, &actions)
42
+ event_token = "wf_#{e}"
43
+ map_token = "#{event_token}_transition_map"
44
+
45
+ #setup a transition map class instance variable and corresponding accessors for each event.
46
+ self.class_eval("@#{map_token}={}")
47
+ self.class_eval("def self.#{map_token}; return @#{map_token}; end")
48
+ self.class_eval("def self.wf_current_event_transition_map=(cem); @wf_current_event_transition_map=cem; end" )
49
+ self.class_eval("@wf_current_event_transition_map = @#{map_token}={}")
50
+ self.class_eval("def self.wf_current_event_transition_map; @wf_current_event_transition_map; end" )
51
+ self.class_eval("def self.wf_current_event_transition_map=(cem); @wf_current_event_transition_map=cem; end" )
52
+
53
+ #instance event_methods
54
+ self.class_eval("def #{event_token}; self._wf_current_event_transition_map=self.class.#{map_token}; _set_workflow_state \"#{e}\"; end\n")
55
+ self.class_eval("def #{event_token}!; #{event_token}; _wf_after_transition_save!; wf_after_save if self.class.method_defined? :wf_after_save; end\n" )
56
+
57
+ #Calls transitions in event block
58
+ actions.call
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ private
65
+
66
+ def _set_workflow_state(event=nil)
67
+ self.wf_previous_state = self.wf_current_state
68
+ self.wf_last_event = event if self.respond_to?(:wf_last_event)
69
+
70
+ state = self._wf_current_event_transition_map[self.wf_current_state] || self._wf_current_event_transition_map[:any]
71
+
72
+ if (state != self.wf_current_state) && (!state.nil?)
73
+ self.wf_current_state=state
74
+
75
+ eval("wf_on_#{event}") if event && (self.class.method_defined? "wf_on_#{event}")
76
+ eval("wf_on_exit_#{wf_current_state}") if self.class.method_defined? "wf_on_exit_#{wf_current_state}"
77
+ eval("wf_on_enter_#{state}") if self.class.method_defined? "wf_on_enter_#{state}"
78
+
79
+ wf_after_transition if self.class.method_defined? :wf_after_transition
80
+ end
81
+ end
82
+
83
+ def _wf_after_transition_save!
84
+ self.wf_state = self.wf_current_state if self.respond_to?(:wf_state=)
85
+ save! if self.respond_to?(:save!)
86
+ end
87
+
88
+ end
89
+
90
+
91
+
@@ -0,0 +1,115 @@
1
+ require 'rubygems'
2
+ require 'active_record'
3
+ require 'test/unit'
4
+ require 'flojo'
5
+ require 'test_helper'
6
+
7
+ ActiveRecord::Base.establish_connection(
8
+ :adapter => "sqlite3",
9
+ :database => "test/test_db.sqlite3"
10
+ )
11
+
12
+ class Counter < ActiveRecord::Base
13
+ include Flojo
14
+
15
+ workflow_states [:one, :two, :three, :four]
16
+
17
+ event :up do
18
+ transition :one, :two
19
+ transition :two, :three
20
+ transition :three, :four
21
+ end
22
+
23
+ event :reset do
24
+ transition :two, :one
25
+ transition :three, :one
26
+ transition :four, :one
27
+ end
28
+
29
+ event :down do
30
+ transition :one, :three
31
+ transition :two, :one
32
+ transition :three, :two
33
+ end
34
+
35
+ def wf_on_enter_one
36
+ "on_enter_one"
37
+ end
38
+
39
+ def wf_on_exit_one
40
+ "on_exit_one"
41
+ end
42
+
43
+ def wf_on_down
44
+ "on_down"
45
+ end
46
+
47
+ def wf_on_up
48
+ "on_up"
49
+ end
50
+
51
+ def wf_after_transition
52
+ "wf_after_transition"
53
+ end
54
+
55
+ def wf_after_save
56
+ "wf_after_save"
57
+ end
58
+
59
+ end
60
+
61
+
62
+ class TestWorkflow < Test::Unit::TestCase
63
+ include CommonTests
64
+ def setup
65
+ Counter.delete_all
66
+ @b = Baby.new
67
+ @c = Counter.new
68
+ @c.name = "First"
69
+ @c.save
70
+ end
71
+
72
+ def teardown
73
+ Counter.delete_all
74
+ end
75
+
76
+ def test_stored_counter
77
+ stored_counter = Counter.first
78
+ assert_equal(:one, stored_counter.wf_current_state, "Initial state must be :one")
79
+
80
+ stored_counter.wf_up!
81
+ assert_equal(:two, stored_counter.wf_current_state, "Current state must be :two")
82
+
83
+ stored_counter.reload
84
+ assert_equal("two", stored_counter.wf_state, "Stored state must be two")
85
+ assert_equal(:two, stored_counter.wf_current_state, "Current state must be :two")
86
+
87
+ stored_counter.wf_state = "three"
88
+ stored_counter.save!
89
+
90
+ assert_equal("three", stored_counter.wf_state, "Stored state must be three")
91
+
92
+ stored_counter = Counter.first
93
+ assert_equal(:three, stored_counter.wf_current_state, "Current state must be :three")
94
+ end
95
+
96
+ def test_new_counter
97
+ new_counter = Counter.new
98
+ assert_equal(nil, new_counter.wf_state, "Stored state must be nil")
99
+ assert_equal(:one, new_counter.wf_current_state, "Initial state must be :one")
100
+ assert_equal(1, Counter.count)
101
+
102
+ new_counter.wf_up!
103
+ assert_equal(2, Counter.count)
104
+ assert_equal("up", new_counter.wf_last_event)
105
+
106
+ new_counter = Counter.last
107
+ assert_equal("two", new_counter.wf_state, "Stored state must be nil")
108
+ assert_equal(:two, new_counter.wf_current_state, "Initial state must be :two")
109
+ assert_equal("up", new_counter.wf_last_event)
110
+ new_counter.wf_down
111
+ assert_equal("down", new_counter.wf_last_event)
112
+
113
+ end
114
+
115
+ end
Binary file
@@ -0,0 +1,124 @@
1
+ module CommonTests
2
+ def test_events
3
+ assert_equal(:one, @c.wf_current_state, "Initial state must be :one")
4
+ assert_equal(@c.wf_up!, "wf_after_save", "Last method called should be wf_after_save hook")
5
+ assert_equal(:one, @c.wf_previous_state)
6
+ assert_equal(:two, @c.wf_current_state)
7
+
8
+ @c.wf_down!
9
+
10
+ assert_equal(:one, @c.wf_current_state)
11
+
12
+ assert_respond_to(@c, :wf_up!)
13
+ assert_respond_to(@c, :wf_down!)
14
+ assert_respond_to(@c, :wf_reset!)
15
+
16
+ @c.wf_up #to :two
17
+ @c.wf_up #to :three
18
+
19
+ @c.wf_up #to :four
20
+
21
+ @c.wf_up #to :four
22
+
23
+ assert_nil(@c.wf_up, "No transition expected")
24
+
25
+ @c.wf_up! #to :four
26
+
27
+ assert_nil(@c.wf_up, "No transition expected")
28
+
29
+ assert(@c.wf_four?, "Should still be at :four")
30
+
31
+ end
32
+
33
+ def test_states
34
+ assert_equal(Counter.wf_states, [:one, :two, :three, :four])
35
+ assert_equal(Baby.wf_states, [:asleep, :crying, :pooping, :chilling, :puking] )
36
+ assert_respond_to(@c, :wf_one?)
37
+ assert_respond_to(@c, :wf_two?)
38
+ assert_respond_to(@c, :wf_three?)
39
+ assert_respond_to(@c, :wf_four?)
40
+
41
+ #states are mutually exclusive and there is always one state
42
+ assert(@c.wf_one? || @c.wf_two? || @c.wf_three? || @c.wf_four?)
43
+ assert(!(@c.wf_one? && @c.wf_two? && @c.wf_three? && @c.wf_four?))
44
+
45
+ @c.wf_up! #to :two
46
+ assert(@c.wf_two?)
47
+ assert(!(@c.wf_one? || @c.wf_three? || @c.wf_four?))
48
+
49
+ end
50
+
51
+ def test_wildcard
52
+ assert_equal(@b.wf_current_state, :asleep)
53
+ assert(@b.wf_asleep?, "Initial state is asleep")
54
+ @b.wf_spank; assert(@b.wf_crying?, "Spanking must always lead to crying")
55
+ @b.wf_feed; assert(@b.wf_chilling?, "Feed must move from crying to chilling")
56
+ @b.wf_burp; assert(@b.wf_puking?, "Burp must move from chilling to puking")
57
+ @b.wf_spank; assert(@b.wf_crying?, "Spanking must always lead to crying")
58
+ @b.wf_rock; assert(@b.wf_chilling?, "Rock must move from crying to chilling")
59
+ @b.wf_spank; assert(@b.wf_crying?, "Spanking must always lead to crying")
60
+ end
61
+
62
+ def test_inheritance
63
+ oc = OtherCounter.new
64
+ assert(oc.wf_a?)
65
+ oc.wf_up; assert(oc.wf_b?, "State must be :b after wf_up")
66
+ end
67
+ end
68
+
69
+ class Baby
70
+ include Flojo
71
+
72
+ workflow_states [:asleep, :crying, :pooping, :chilling, :puking]
73
+
74
+ event :feed do
75
+ transition :crying, :chilling
76
+ transition :chilling, :pooping
77
+ end
78
+
79
+ event :rock do
80
+ transition :crying, :chilling
81
+ transition :chilling, :asleep
82
+ transition :asleep, :pooping
83
+ end
84
+
85
+ event :burp do
86
+ transition :crying, :chilling
87
+ transition :chilling, :puking
88
+ end
89
+
90
+ event :wake do
91
+ transition :asleep, :crying
92
+ end
93
+
94
+ event :spank do
95
+ transition :any, :crying
96
+ end
97
+
98
+ #enter and exit event handlers should take the form on_enter_xxx, on_exit_xxx where xxx is the state
99
+ def wf_on_enter_asleep
100
+ puts "I peed all over the bed"
101
+ end
102
+
103
+ def wf_on_enter_chilling
104
+ puts "drool and fart"
105
+ end
106
+
107
+ def wf_on_exit_asleep
108
+ puts "waaaaah waaaaah waaaaaah"
109
+ end
110
+
111
+ end
112
+
113
+
114
+ class OtherCounter < Baby
115
+ include Flojo
116
+
117
+ workflow_states [:a, :b, :c, :d]
118
+
119
+ event :up do
120
+ transition :a, :b
121
+ transition :b, :c
122
+ transition :c, :d
123
+ end
124
+ end
data/test/test_poro.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'flojo'
2
+ require 'test/unit'
3
+ require 'test_helper'
4
+
5
+ class Counter
6
+ include Flojo
7
+
8
+ workflow_states [:one, :two, :three, :four]
9
+
10
+ event :up do
11
+ transition :one, :two
12
+ transition :two, :three
13
+ transition :three, :four
14
+ end
15
+
16
+ event :reset do
17
+ transition :two, :one
18
+ transition :three, :one
19
+ transition :four, :one
20
+ end
21
+
22
+ event :down do
23
+ transition :one, :three
24
+ transition :two, :one
25
+ transition :three, :two
26
+ end
27
+
28
+ #enter and exit event handlers should take the form on_enter_xxx, on_exit_xxx where xxx is the state
29
+ def wf_on_enter_one
30
+ "on_enter_one"
31
+ end
32
+
33
+ def wf_on_exit_one
34
+ "on_exit_one"
35
+ end
36
+
37
+ def wf_on_down
38
+ "on_down"
39
+ end
40
+
41
+ def wf_on_up
42
+ "on_up"
43
+ end
44
+
45
+
46
+ def wf_after_transition
47
+ "wf_after_transition"
48
+ end
49
+
50
+ def wf_after_save
51
+ "wf_after_save"
52
+ end
53
+
54
+
55
+ end
56
+
57
+
58
+ class TestState < Test::Unit::TestCase
59
+ include CommonTests
60
+
61
+ def setup
62
+ @c = Counter.new
63
+ @b = Baby.new
64
+ end
65
+
66
+ end
67
+
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flojo
3
+ version: !ruby/object:Gem::Version
4
+ hash: 11
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 5
9
+ - 0
10
+ version: 0.5.0
11
+ platform: ruby
12
+ authors:
13
+ - Joey Adarkwah
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-07 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: ActiveRecord aware workflow (state machine) module that will also work with any plain old ruby object.
23
+ email: alternegro @nospam@ me.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - CHANGELOG
30
+ - README.rdoc
31
+ - lib/flojo.rb
32
+ files:
33
+ - CHANGELOG
34
+ - MIT_LICENSE
35
+ - README.rdoc
36
+ - Rakefile
37
+ - flojo.gemspec
38
+ - lib/flojo.rb
39
+ - test/test_active_record.rb
40
+ - test/test_db.sqlite3
41
+ - test/test_helper.rb
42
+ - test/test_poro.rb
43
+ - Manifest
44
+ has_rdoc: true
45
+ homepage: http://github.com/alternegro/flojo
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --line-numbers
51
+ - --inline-source
52
+ - --title
53
+ - Flojo
54
+ - --main
55
+ - README.rdoc
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 11
73
+ segments:
74
+ - 1
75
+ - 2
76
+ version: "1.2"
77
+ requirements: []
78
+
79
+ rubyforge_project: flojo
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: "When used within an ActiveRecord subclass, flojo events can automatically save a record after a transition. After including the module in your class and configuring it with an event _event_, and a state _state_, you can interact with instances of that class using the dynamically generated methods of the following form: +object.wf_event+ - Triggers event and invokes any applicable transitions +object.wf_event!+ - Behaves just like +object.wf_event+ but will also persist object. +object.wf_state?+ - Returns true if the current workflow state is _state_. +object.wf_current_state+ - Returns the objects current state."
84
+ test_files:
85
+ - test/test_active_record.rb
86
+ - test/test_helper.rb
87
+ - test/test_poro.rb