state-fu 0.12.3 → 0.13.0

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