state-fu 0.12.3 → 0.13.0

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.
@@ -2,6 +2,6 @@ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
2
 
3
3
  describe "using StateFu w/ shared logs" do
4
4
  it "should be sane" do
5
- StateFu::Logger.shared?.should == false
5
+ StateFu::Logging.shared?.should == false
6
6
  end
7
7
  end
@@ -4,7 +4,7 @@ describe "an ActiveRecord model with StateFu included:" do
4
4
 
5
5
  include MySpecHelper
6
6
 
7
- before(:each) do
7
+ before(:all) do
8
8
  reset!
9
9
  prepare_active_record() do
10
10
  def self.up
@@ -48,7 +48,8 @@ describe "an ActiveRecord model with StateFu included:" do
48
48
  before do
49
49
  ExampleRecord.class_eval do
50
50
  state_fu_machine do
51
- state :initial do
51
+ state :initial do
52
+ # an after transition hook saves the record
52
53
  event( :change, :to => :final ) { after :save! }
53
54
  end
54
55
  end
@@ -84,9 +85,9 @@ describe "an ActiveRecord model with StateFu included:" do
84
85
  it "should return false for ExampleRecord, :not_a_column" do
85
86
  StateFu::Persistence.active_record_column?( ExampleRecord, :not_a_column ).should == false
86
87
  end
88
+
87
89
  it "should not clobber activerecord accessors" do
88
90
  @ex.noodle! rescue nil
89
- # lambda { @ex.description }.should_not raise_error()
90
91
  @ex.description.should be_nil
91
92
  @ex.description= 'foo'
92
93
  @ex.description.should == 'foo'
@@ -122,12 +123,6 @@ describe "an ActiveRecord model with StateFu included:" do
122
123
  @ex.save!
123
124
  end
124
125
 
125
- it "should fail to save if state_fu! does not instantiate the binding before create" do
126
- mock( @ex ).state_fu!.at_least( 1 ) { }
127
- lambda { @ex.save! }.should raise_error( ActiveRecord::StatementInvalid )
128
- @ex.state_fu_field.should == nil
129
- end
130
-
131
126
  it "should create a record given only a name, with the field set to the initial state" do
132
127
  ex = ExampleRecord.new( :name => "exemplar" )
133
128
  ex.should be_valid
@@ -166,7 +161,7 @@ describe "an ActiveRecord model with StateFu included:" do
166
161
  end
167
162
  end # saved record after transition
168
163
 
169
- describe "when a second machine named :status is defined with :field_name => 'status' " do
164
+ describe "when a second machine named :status is defined with :field_name => 'status'" do
170
165
  before do
171
166
  ExampleRecord.state_fu_machine(:status, :field_name => 'status') do
172
167
  event( :go, :from => :initial, :to => :final )
@@ -196,7 +191,20 @@ describe "an ActiveRecord model with StateFu included:" do
196
191
  @ex.status= 'damp'
197
192
  lambda { @ex.status }.should raise_error( StateFu::InvalidStateName )
198
193
  end
194
+ end # second machine
195
+
196
+ describe "coexisting with an attribute-backed machine" do
197
+ it "should get along merrily" do
198
+ ExampleRecord.machine(:temporary, :field_name => 'temp') do
199
+ state :new
200
+ end
201
+ @ex = ExampleRecord.new()
202
+ @ex.temporary.should == :new
203
+ @ex.instance_variable_get("@temp").should == 'new'
204
+ @ex.temporary.persister.class.should == StateFu::Persistence::Attribute
205
+ end
199
206
  end
200
- end # second machine
201
- end # with before_create filter
202
- end # default machine
207
+
208
+ end
209
+ end
210
+ end
@@ -106,12 +106,13 @@ describe "Document" do
106
106
  # lambda { @doc.status_field }.should raise_error()
107
107
  # end
108
108
 
109
- it "should be defined before state_fu is called" do
110
- @doc.send( :status_field ).should == 'draft'
109
+ it "should be nil before state_fu is called" do
110
+ @doc.send(:status_field).should == nil
111
111
  end
112
112
 
113
- it "should have an initial value of 'draft'" do
114
- @doc.instance_eval { status_field }.should == "draft"
113
+ it "should have an initial value of 'draft' once the binding is referenced" do
114
+ @doc.status # initialize the machine
115
+ @doc.send(:status_field).should == 'draft'
115
116
  end
116
117
 
117
118
  it "should be set to 'published' after publish! is called successfully" do
@@ -172,9 +172,10 @@ describe "Transition requirement reflection" do
172
172
  stub( @obj ).spacesuit?() { false }
173
173
  stub( @obj ).fuel?() { false }
174
174
  end
175
+
175
176
  describe "when the arity of the proc is 1" do
176
177
  before do
177
- @msg = lambda { |trans| "I am a #{trans.class} and I fail it" }
178
+ @msg = lambda { |transition| "No #{transition.target.name} for you!" }
178
179
  @machine.requirement_messages[:spacesuit?] = @msg
179
180
  end
180
181
 
@@ -186,14 +187,14 @@ describe "Transition requirement reflection" do
186
187
  messages.length.should == 2
187
188
  messages.strings.length.should == 1
188
189
  messages.strings.first.should be_kind_of( String )
189
- messages.strings.first.should == "I am a StateFu::Transition and I fail it"
190
+ messages.strings.first.should == "No moon for you!"
190
191
  messages.symbols.first.should == :fuel?
191
192
  end
192
193
  end # arity 1
193
194
 
194
195
  describe "when the arity of the proc is 0" do
195
196
  before do
196
- @msg = lambda { "No #{t.target.name} for you!" }
197
+ @msg = lambda { "No soup for you!" }
197
198
  @machine.requirement_messages[:spacesuit?] = @msg
198
199
  end
199
200
 
@@ -205,7 +206,7 @@ describe "Transition requirement reflection" do
205
206
  messages.length.should == 2
206
207
  messages.strings.length.should == 1
207
208
  messages.strings.first.should be_kind_of( String )
208
- messages.strings.first.should == "No moon for you!"
209
+ messages.strings.first.should == "No soup for you!"
209
210
  messages.symbols.first.should == :fuel?
210
211
  end
211
212
  end # arity 1
@@ -660,8 +660,8 @@ describe StateFu::Transition do
660
660
  before do
661
661
  Klass.state_fu_machine do
662
662
  event( :go ) do
663
- execute do
664
- halt!("stop")
663
+ execute do |transition|
664
+ transition.halt!("stop")
665
665
  end
666
666
  end
667
667
  end
data/spec/spec_helper.rb CHANGED
@@ -12,8 +12,8 @@ require 'spec'
12
12
  # record the log output on each run
13
13
  LOGFILE = File.join('log', 'spec.log') unless Object.const_defined?('LOGFILE')
14
14
  FileUtils.rm LOGFILE if File.exists?(LOGFILE)
15
- StateFu::Logger.level = Logger::INFO
16
- StateFu::Logger.logger = Logger.new(LOGFILE)
15
+ StateFu::Logging.level = Logger::INFO
16
+ StateFu::Logging.logger = Logger.new(LOGFILE)
17
17
 
18
18
  module MySpecHelper
19
19
  include NoStdout
@@ -79,41 +79,35 @@ describe "A door which opens and shuts:" do
79
79
 
80
80
  describe "magic event methods" do
81
81
 
82
- it "doesn't normally have a method #shut!" do
83
- @door.respond_to?(:shut!).should == false
84
- end
85
-
86
- it "will define #shut! when method_missing is called for the first time" do
87
- begin
88
- @door.play_the_ukelele
89
- rescue NoMethodError
90
- end
91
- @door.respond_to?(:shut!).should == true
92
- end
93
-
94
- it "will keep any existing methods when method_missing is triggered" do
95
- @door.respond_to?(:shut).should == true
96
- @door.respond_to?(:can_shut?).should == false
97
- @door.shut.should == "I don't know how to shut!"
98
- @door.can_shut?.should == true # triggers method_missing
99
- @door.respond_to?(:shut).should == true
100
- @door.respond_to?(:can_shut?).should == true # new methods defined
101
- @door.shut.should == "I don't know how to shut!" # old method retained
102
- end
103
-
104
- it "gets a set of new methods when any magic method is called" do
105
- @door.respond_to?(:shut).should == true # already defined
106
- @door.respond_to?(:open).should == false
107
- @door.respond_to?(:can_shut?).should == false
108
- @door.respond_to?(:can_open?).should == false
109
- @door.respond_to?(:shut!).should == false
110
- @door.respond_to?(:open!).should == false
111
- @door.can_shut?.should == true # call one of them (triggers method_missing)
112
- @door.respond_to?(:open).should == false # a private method: Kernel#open
113
- @door.respond_to?(:can_shut?).should == true # but these are all newly defined public methods
114
- @door.respond_to?(:can_open?).should == true
115
- @door.respond_to?(:shut!).should == true
116
- @door.respond_to?(:open!).should == true
82
+ # it "doesn't normally have a method #shut!" do
83
+ # @door.respond_to?(:shut!).should == false
84
+ # end
85
+ #
86
+ # it "will define #shut! when method_missing is called for the first time" do
87
+ # begin
88
+ # @door.play_the_ukelele
89
+ # rescue NoMethodError
90
+ # end
91
+ # @door.respond_to?(:shut!).should == true
92
+ # end
93
+
94
+ # it "will keep any existing methods when method_missing is triggered" do
95
+ # @door.respond_to?(:shut).should == true
96
+ # @door.respond_to?(:can_shut?).should == false
97
+ # @door.shut.should == "I don't know how to shut!"
98
+ # @door.can_shut?.should == true # triggers method_missing
99
+ # @door.respond_to?(:shut).should == true
100
+ # @door.respond_to?(:can_shut?).should == true # new methods defined
101
+ # @door.shut.should == "I don't know how to shut!" # old method retained
102
+ # end
103
+
104
+ it "TODO RENAME THIS SPEC" do
105
+ @door.respond_to?(:open).should == false # a private method: Kernel#open
106
+ @door.respond_to?(:open, true).should == true
107
+ @door.respond_to?(:can_shut?).should == true # but these are all newly defined public methods
108
+ @door.respond_to?(:can_open?).should == true
109
+ @door.respond_to?(:shut!).should == true
110
+ @door.respond_to?(:open!).should == true
117
111
  end
118
112
 
119
113
  it "retains any previously defined method_missing" do
@@ -160,9 +154,6 @@ describe "A door which opens and shuts:" do
160
154
 
161
155
  describe "magic state methods" do
162
156
  it "should be defined for each state by method_missing voodoo" do
163
- @door.should_not respond_to(:closed?)
164
- @door.should_not respond_to(:open?)
165
- @door.open?.should == true
166
157
  @door.should respond_to(:closed?)
167
158
  @door.should respond_to(:open?)
168
159
  end
@@ -181,7 +172,6 @@ describe "A door which opens and shuts:" do
181
172
 
182
173
  it "#can_shut? when the current state is open" do
183
174
  @door.current_state.should == :open
184
- # @door.state_fu.valid_transitions.map(&:destination).inspect
185
175
  @door.can_shut?.should == true
186
176
  @door.can_open?.should == nil # not a valid transition from this state -> nil
187
177
  end
@@ -208,7 +198,7 @@ describe "A door which opens and shuts:" do
208
198
  it "raises StateFu::RequirementError if #open! is called when it is locked" do
209
199
  @door.shut!
210
200
  @door.locked = true
211
- lambda { @door.open! }.should raise_error(StateFu::RequirementError)
201
+ lambda { @door.open! }.should raise_error( StateFu::RequirementError )
212
202
  end
213
203
 
214
204
  it "tells you why it won't open if you ask nicely" do
@@ -551,15 +541,14 @@ describe "arguments given to different method signatures" do
551
541
  def b2(t,a=nil) received[:b2] = [t,a] end
552
542
  def c2(t,*a) received[:c2] = [t,a] end
553
543
 
554
- # these method signatures get a transition, a list of arguments,
555
- # and the object which owns the machine
544
+ # these method signatures take too many arguments and will cause an ArgumentError
556
545
  def a3(t,a,o) received[:a3] = [t,a,o] end
557
546
  def b3(t,a,o=nil) received[:b3] = [t,a,o] end
558
547
  def c3(t,a,*o) received[:c3] = [t,a,o] end
559
548
 
560
549
  machine do
561
550
  cycle :state => :observing, :on => :observe do
562
- trigger :a1, :b1, :c1, :a2, :b2, :c2, :a3, :b3, :c3
551
+ trigger :a1, :b1, :c1, :a2, :b2, :c2
563
552
  end
564
553
  end
565
554
 
@@ -572,7 +561,7 @@ describe "arguments given to different method signatures" do
572
561
  end
573
562
 
574
563
  it "have a list of execute hooks" do
575
- Recorder.machine.events[:observe].hooks[:execute].should == [:a1, :b1, :c1, :a2, :b2, :c2, :a3, :b3, :c3]
564
+ Recorder.machine.events[:observe].hooks[:execute].should == [:a1, :b1, :c1, :a2, :b2, :c2]
576
565
  end
577
566
  end
578
567
 
@@ -595,7 +584,7 @@ describe "arguments given to different method signatures" do
595
584
  end
596
585
 
597
586
  it "call the event's :execute hooks on #observe!" do
598
- @results.keys.should =~ [:a1, :b1, :c1, :a2, :b2, :c2, :a3, :b3, :c3]
587
+ @results.keys.should =~ [:a1, :b1, :c1, :a2, :b2, :c2]
599
588
  end
600
589
 
601
590
  describe "methods which expect one argument" do
@@ -615,10 +604,13 @@ describe "arguments given to different method signatures" do
615
604
  end
616
605
 
617
606
  describe "methods which expect three arguments" do
618
- it "receive a StateFu::Transition, an argument list and the recorder object" do
619
- @results[:a3].should == [@t, @t.args, @recorder]
620
- @results[:b3].should == [@t, @t.args, @recorder]
621
- @results[:c3].should == [@t, @t.args, [@recorder]]
607
+ it "raise an ArgumentError" do
608
+ [:a1, :b1, :c1, :a2, :b2, :c2].each do |meth|
609
+ @t.call(meth)
610
+ end
611
+ [:a3, :b3, :c3].each do |meth|
612
+ lambda { @t.call(:a3) }.should raise_error(ArgumentError)
613
+ end
622
614
  end
623
615
  end
624
616
  end
@@ -734,7 +726,8 @@ describe "sitting at a poker machine" do
734
726
 
735
727
  event :stop_spinning, :to => :ready do
736
728
  requires :wheels_stopped?
737
- execute :payout do
729
+ execute :payout do |transition|
730
+ wheel_states = transition.call(:wheel_states)
738
731
  if wheel_states == wheel_states.uniq
739
732
  self.credits += wheel_states.first[:value]
740
733
  end
@@ -756,7 +749,7 @@ describe "sitting at a poker machine" do
756
749
  execute do
757
750
  silly_noises_inflicted << :spinning_noise
758
751
  end
759
- after do
752
+ after do |transition, *args|
760
753
  if rand(3) == 0
761
754
  # we use binding.stop! rather than self.stop! here
762
755
  # to disambiguate which machine we're sending the event to.
@@ -769,7 +762,7 @@ describe "sitting at a poker machine" do
769
762
  # (the first one, becuase it was defined first, and automatically
770
763
  # defined methods never clobber any pre-existing methods) -
771
764
  # which isn't what we want here.
772
- binding.stop!([:bomb, :cherry, :smiley, :gold].rand)
765
+ transition.binding.stop!([:bomb, :cherry, :smiley, :gold].rand)
773
766
  end
774
767
  end
775
768
  end
@@ -27,7 +27,7 @@ describe StateFu::Binding do
27
27
 
28
28
  describe "constructor" do
29
29
  before do
30
- mock(Klass).state_fu_options.at_most(2) do
30
+ mock(Klass).state_fu_options.at_most(3) do
31
31
  {
32
32
  :example => {:field_name => :example_field}
33
33
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: state-fu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.3
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Lee
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-08 00:00:00 +11:00
12
+ date: 2009-10-17 00:00:00 +11:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -62,8 +62,7 @@ files:
62
62
  - lib/support/core_ext.rb
63
63
  - lib/support/exceptions.rb
64
64
  - lib/support/has_options.rb
65
- - lib/support/logger.rb
66
- - lib/support/methodical.rb
65
+ - lib/support/logging.rb
67
66
  - lib/support/no_stdout.rb
68
67
  - lib/support/plotter.rb
69
68
  - lib/support/vizier.rb
@@ -72,9 +71,9 @@ files:
72
71
  - lib/transition.rb
73
72
  - lib/transition_query.rb
74
73
  - spec/custom_formatter.rb
74
+ - spec/features/active_record_auto_save_spec.rb
75
75
  - spec/features/binding_and_transition_helper_mixin_spec.rb
76
76
  - spec/features/machine_alias_spec.rb
77
- - spec/features/method_missing_only_once_spec.rb
78
77
  - spec/features/not_requirements_spec.rb
79
78
  - spec/features/plotter_spec.rb
80
79
  - spec/features/shared_log_spec.rb
@@ -139,9 +138,9 @@ specification_version: 3
139
138
  summary: A rich library for state-oriented programming with state machines / workflows
140
139
  test_files:
141
140
  - spec/custom_formatter.rb
141
+ - spec/features/active_record_auto_save_spec.rb
142
142
  - spec/features/binding_and_transition_helper_mixin_spec.rb
143
143
  - spec/features/machine_alias_spec.rb
144
- - spec/features/method_missing_only_once_spec.rb
145
144
  - spec/features/not_requirements_spec.rb
146
145
  - spec/features/plotter_spec.rb
147
146
  - spec/features/shared_log_spec.rb
@@ -1,17 +0,0 @@
1
- module StateFu
2
- module Methodical
3
-
4
- def self.__define_method( method_name, &block )
5
- self.class.class_eval do
6
- define_method method_name, &block
7
- end
8
- end
9
-
10
- def __define_singleton_method( method_name, &block )
11
- (class << object; self; end).class_eval do
12
- define_method method_name, &block
13
- end
14
- end
15
-
16
- end
17
- end
@@ -1,28 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
-
3
- describe "method_missing" do
4
- include MySpecHelper
5
- before do
6
- make_pristine_class('Klass')
7
- Klass.state_fu_machine() {}
8
- @obj = Klass.new
9
- end
10
-
11
- it "should revert to the original method_missing after it is called once" do
12
- mock.proxy( @obj ).state_fu!.times(1)
13
- mm1 = @obj.method(:method_missing)
14
- call_snafu = lambda do
15
- begin
16
- @obj.snafu!
17
- rescue NoMethodError
18
- end
19
- end
20
- call_snafu.call()
21
- mm2 = @obj.method(:method_missing)
22
- mm1.should_not == mm2
23
- call_snafu.call()
24
- mm3 = @obj.method(:method_missing)
25
- mm3.should == mm2
26
- # @obj.snafu
27
- end
28
- end