davidlee-state-fu 0.0.1

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.
Files changed (49) hide show
  1. data/LICENSE +40 -0
  2. data/README.textile +174 -0
  3. data/Rakefile +87 -0
  4. data/lib/no_stdout.rb +32 -0
  5. data/lib/state-fu.rb +93 -0
  6. data/lib/state_fu/binding.rb +262 -0
  7. data/lib/state_fu/core_ext.rb +23 -0
  8. data/lib/state_fu/event.rb +98 -0
  9. data/lib/state_fu/exceptions.rb +42 -0
  10. data/lib/state_fu/fu_space.rb +50 -0
  11. data/lib/state_fu/helper.rb +189 -0
  12. data/lib/state_fu/hooks.rb +28 -0
  13. data/lib/state_fu/interface.rb +139 -0
  14. data/lib/state_fu/lathe.rb +247 -0
  15. data/lib/state_fu/logger.rb +10 -0
  16. data/lib/state_fu/machine.rb +159 -0
  17. data/lib/state_fu/method_factory.rb +95 -0
  18. data/lib/state_fu/persistence/active_record.rb +27 -0
  19. data/lib/state_fu/persistence/attribute.rb +46 -0
  20. data/lib/state_fu/persistence/base.rb +98 -0
  21. data/lib/state_fu/persistence/session.rb +7 -0
  22. data/lib/state_fu/persistence.rb +50 -0
  23. data/lib/state_fu/sprocket.rb +27 -0
  24. data/lib/state_fu/state.rb +45 -0
  25. data/lib/state_fu/transition.rb +213 -0
  26. data/spec/helper.rb +86 -0
  27. data/spec/integration/active_record_persistence_spec.rb +189 -0
  28. data/spec/integration/class_accessor_spec.rb +127 -0
  29. data/spec/integration/event_definition_spec.rb +74 -0
  30. data/spec/integration/ex_machine_for_accounts_spec.rb +79 -0
  31. data/spec/integration/example_01_document_spec.rb +127 -0
  32. data/spec/integration/example_02_string_spec.rb +87 -0
  33. data/spec/integration/instance_accessor_spec.rb +100 -0
  34. data/spec/integration/machine_duplication_spec.rb +95 -0
  35. data/spec/integration/requirement_reflection_spec.rb +201 -0
  36. data/spec/integration/sanity_spec.rb +31 -0
  37. data/spec/integration/state_definition_spec.rb +177 -0
  38. data/spec/integration/transition_spec.rb +1060 -0
  39. data/spec/spec.opts +7 -0
  40. data/spec/units/binding_spec.rb +145 -0
  41. data/spec/units/event_spec.rb +232 -0
  42. data/spec/units/exceptions_spec.rb +75 -0
  43. data/spec/units/fu_space_spec.rb +95 -0
  44. data/spec/units/lathe_spec.rb +567 -0
  45. data/spec/units/machine_spec.rb +237 -0
  46. data/spec/units/method_factory_spec.rb +359 -0
  47. data/spec/units/sprocket_spec.rb +71 -0
  48. data/spec/units/state_spec.rb +50 -0
  49. metadata +122 -0
@@ -0,0 +1,567 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe StateFu::Lathe do
4
+ include MySpecHelper
5
+
6
+ before do
7
+ reset!
8
+ make_pristine_class('Klass')
9
+ @machine = Object.new()
10
+ @state = Object.new()
11
+ @event = Object.new()
12
+
13
+ @lathe = StateFu::Lathe.new( @machine )
14
+ @states = [].extend StateFu::StateArray
15
+ stub( @machine ).states() { @states }
16
+ @events = [].extend StateFu::EventArray
17
+ stub( @machine ).events() { @events }
18
+ end
19
+
20
+ describe "constructor" do
21
+ it "should create a new Lathe given valid arguments" do
22
+ lathe = StateFu::Lathe.new( @machine )
23
+ lathe.should be_kind_of( StateFu::Lathe )
24
+ lathe.machine.should == @machine
25
+ lathe.sprocket.should == nil
26
+ lathe.options.should == {}
27
+ end
28
+
29
+ it "should accept a sprocket (state / event ) and if given one, be a child" do
30
+ options = {}
31
+ mock( @state ).apply!( options ) {}
32
+ lathe = StateFu::Lathe.new( @machine, @state )
33
+ lathe.should be_kind_of( StateFu::Lathe )
34
+ lathe.machine.should == @machine
35
+ lathe.sprocket.should == @state
36
+ lathe.options.should == {}
37
+ lathe.should be_child
38
+ end
39
+ end
40
+
41
+ describe "lathe instance with no sprocket (master lathe for a machine)" do
42
+ before do
43
+ end
44
+
45
+ it "should be master?" do
46
+ @lathe.should be_master
47
+ @lathe.should_not be_child
48
+ end
49
+
50
+ describe "defining a state with .state" do
51
+
52
+ it "should add a state to the lathe's machine.states if the named state does not exist" do
53
+ @lathe.state( :wibble )
54
+ @machine.states.should_not be_empty
55
+ @machine.states.length.should == 1
56
+ s = @machine.states.first
57
+ s.should be_kind_of( StateFu::State )
58
+ s.name.should == :wibble
59
+ end
60
+
61
+ it "should create a child lathe and apply the options and block if supplied" do
62
+ options = {:banana => :flower}
63
+ @state = Object.new()
64
+ @child = Object.new()
65
+ # can't mock the block :(
66
+ mock( StateFu::State ).new( @machine, :wobble, options ) { @state }
67
+ mock( StateFu::Lathe ).new( @machine, @state, options ) { @child }
68
+ mock( @child )
69
+ @lathe.state( :wobble, options )
70
+ end
71
+
72
+ it "should update the named state if it exists" do
73
+ @lathe.state( :wibble, { :nick => :wobble } )
74
+ @machine.states.should_not be_empty
75
+ @machine.states.length.should == 1
76
+ s = @machine.states.first
77
+ @lathe.state( :wibble, { :meta => :voodoo } ).should == s
78
+ s.options[:meta].should == :voodoo
79
+ s.options[:nick].should == :wobble
80
+ end
81
+
82
+ it "should return the named state" do
83
+ s = @lathe.state( :wibble, { :nick => :wobble } )
84
+ s.should be_kind_of( StateFu::State )
85
+ s.name.should == :wibble
86
+ end
87
+ end # .state
88
+
89
+ describe "defining multiple states with .states" do
90
+
91
+ it "should add all states named to the machine if they dont exist" do
92
+ @lathe.states :a, :b, :c, {:group => :alphabet} do
93
+ requires :jackson_five
94
+ end
95
+ @machine.states.length.should == 3
96
+ @machine.states.map(&:name).should == [:a, :b, :c]
97
+ @machine.states.each {|s| s.options[:group].should == :alphabet }
98
+ @machine.states.each {|s| s.entry_requirements.should include(:jackson_five) }
99
+ end
100
+
101
+ it "should apply the block / options to each named state if it already exists" do
102
+ @lathe.state :lemon do
103
+ requires :squinty_face
104
+ end
105
+ @lathe.states :mango, :orange, :lemon, {:group => :fruit } do
106
+ requires :knife
107
+ on_entry :peel
108
+ end
109
+ @lathe.states :orange, :lemon, :mandarin, { :type => :citrus } do
110
+ requires :juicer
111
+ on_entry :juice
112
+ end
113
+ states = @machine.states
114
+ states[:mango ].options.should == { :group => :fruit }
115
+ states[:lemon ].options.should == { :group => :fruit, :type => :citrus }
116
+ states[:mandarin].options.should == { :type => :citrus }
117
+ states[:mango ].entry_requirements.should == [:knife]
118
+ states[:lemon ].entry_requirements.should == [:squinty_face, :knife, :juicer]
119
+ states[:mandarin].entry_requirements.should == [:juicer]
120
+ states[:mango ].hooks[:entry].should == [:peel]
121
+ states[:lemon ].hooks[:entry].should == [:peel, :juice]
122
+ states[:mandarin].hooks[:entry].should == [:juice]
123
+ end
124
+
125
+ it "should apply to all existing states given :ALL" do
126
+ @lathe.states :hot, :cold
127
+ names = []
128
+ @lathe.states :ALL do |s|
129
+ names << s.name
130
+ end
131
+ names.should == [:hot, :cold]
132
+ end
133
+
134
+ it "should apply to all existing states given no arguments" do
135
+ @lathe.states :hot, :cold
136
+ names = []
137
+ @lathe.states do |s|
138
+ names << s.name
139
+ end
140
+ names.should == [:hot, :cold]
141
+ end
142
+
143
+ # TODO
144
+ it "should apply to all existing states except those named given :except => [...]" do
145
+ @lathe.states :hot, :cold, :warm
146
+
147
+ names = []
148
+ @lathe.states :ALL, :except => :warm do |s|
149
+ names << s.name
150
+ end
151
+ names.should == [:hot, :cold]
152
+
153
+ names = []
154
+ @lathe.states :ALL, :except => [:hot, :cold] do |s|
155
+ names << s.name
156
+ end
157
+ names.should == [:warm]
158
+ end
159
+
160
+ it "should return an array of states with extensions" do
161
+ x = @lathe.states :hot, :cold, :warm
162
+ x.should be_kind_of( Array )
163
+ x.length.should == 3
164
+ x.each {|e| e.should be_kind_of( StateFu::State ) }
165
+ x.map(&:name).should == [:hot, :cold, :warm]
166
+ x.except(:warm).map(&:name).should == [:hot, :cold]
167
+ end
168
+ end # states
169
+
170
+ describe "defining an event with .event" do
171
+
172
+ it "should add a event to the lathe's machine.events if the named event does not exist" do
173
+ @lathe.event( :wibble )
174
+ @machine.events.should_not be_empty
175
+ @machine.events.length.should == 1
176
+ s = @machine.events.first
177
+ s.should be_kind_of( StateFu::Event )
178
+ s.name.should == :wibble
179
+ end
180
+
181
+ it "should create a child lathe and apply the options and block if supplied" do
182
+ options = {:banana => :flower}
183
+ @event = Object.new()
184
+ @child = Object.new()
185
+ # can't mock the block :(
186
+ mock( StateFu::Event ).new( @machine, :wobble, options ) { @event }
187
+ mock( StateFu::Lathe ).new( @machine, @event, options ) { @child }
188
+ mock( @child )
189
+ @lathe.event( :wobble, options )
190
+ end
191
+
192
+ it "should update the named event if it exists" do
193
+ @lathe.event( :wibble )
194
+ @machine.events.should_not be_empty
195
+ @machine.events.length.should == 1
196
+ s = @machine.events.first
197
+ @lathe.event( :wibble, { :meta => :voodoo } ).should == s
198
+ s.options[:meta].should == :voodoo
199
+ end
200
+
201
+ it "should create states mentioned in the event definition and add them to machine.states" do
202
+ @machine = StateFu::Machine.new( :snoo )
203
+ @lathe = StateFu::Lathe.new( @machine )
204
+ @lathe.event(:wobble, :from => [:a, :b], :to => :c )
205
+ @machine.events.should_not be_empty
206
+ @machine.events.length.should == 1
207
+ @machine.events.first.name.should == :wobble
208
+ @machine.states.length.should == 3
209
+ @machine.states.map(&:name).sort_by {|x| x.to_s }.should == [ :a, :b, :c]
210
+ @machine.events[:wobble].origins.map(&:name).should == [:a,:b]
211
+ @machine.events[:wobble].targets.map(&:name).should == [:c]
212
+ end
213
+
214
+ it "should allow definition of events using :from => {*origin => *target}" do
215
+ @machine = StateFu::Machine.new( :hash_it_up )
216
+ @lathe = StateFu::Lathe.new( @machine )
217
+ e = @lathe.event(:snooze, :from => { :nine => :ten } )
218
+ e.name.should == :snooze
219
+ e.origins.length.should == 1
220
+ e.origin.name.should == :nine
221
+ e.targets.length.should == 1
222
+ e.target.name.should == :ten
223
+ end
224
+
225
+ end # .event
226
+
227
+ describe "defining multiple events with .events" do
228
+
229
+ it "should add all events named to the machine if they dont exist" do
230
+ @lathe.event :tickle
231
+ @lathe.events :hit, :smack, :punch, {:group => :acts_of_violence} do
232
+ requires :strong_stomach
233
+ end
234
+ e = @machine.events
235
+ e.length.should == 4
236
+ e.map(&:name).should == [:tickle, :hit, :smack, :punch]
237
+ e[:tickle].options[:group].should == nil
238
+ e[:punch ].options[:group].should == :acts_of_violence
239
+ e[:tickle].requirements.should == []
240
+ e[:punch ].requirements.should == [:strong_stomach]
241
+ end
242
+
243
+ it "should apply the block / options to each named event if it already exists" do
244
+ @lathe.event :fart, { :socially_acceptable => false } do
245
+ requires :tilt_to_one_side
246
+ after :inhale_through_nose
247
+ end
248
+
249
+ @lathe.event :smile, { :socially_acceptable => true } do
250
+ requires :teeth
251
+ after :close_mouth
252
+ end
253
+
254
+ @lathe.events :smile, :fart, { :group => :human_actions } do
255
+ requires :corporeal_body, :free_will
256
+ after :blink
257
+ end
258
+ e = @machine.events
259
+ e[:fart].options[:socially_acceptable].should == false
260
+ e[:smile].options[:socially_acceptable].should == true
261
+ e[:fart].requirements.should == [:tilt_to_one_side, :corporeal_body, :free_will]
262
+ e[:smile].requirements.should == [:teeth, :corporeal_body, :free_will]
263
+ e[:fart].hooks[:after].should == [:inhale_through_nose, :blink]
264
+ e[:smile].hooks[:after].should == [:close_mouth, :blink]
265
+ end
266
+
267
+ it "should apply to all existing events given :ALL" do
268
+ @lathe.events :spit, :run
269
+ names = []
270
+ @lathe.events :ALL do |s|
271
+ names << s.name
272
+ end
273
+ names.should == [:spit, :run]
274
+ end
275
+
276
+ it "should apply to all existing events given no arguments" do
277
+ @lathe.events :dance, :juggle
278
+ names = []
279
+ @lathe.events do |s|
280
+ names << s.name
281
+ end
282
+ names.should == [:dance, :juggle]
283
+ end
284
+
285
+ # TODO
286
+ it "should apply to all existing events except those named given :except => [...]" do
287
+ @lathe.events :wink, :bow, :salute
288
+
289
+ names = []
290
+ @lathe.events :ALL, :except => :salute do |s|
291
+ names << s.name
292
+ end
293
+ names.should == [:wink, :bow]
294
+
295
+ names = []
296
+ @lathe.events :ALL, :except => [:bow, :wink] do |s|
297
+ names << s.name
298
+ end
299
+ names.should == [:salute]
300
+
301
+ end
302
+
303
+ end # events
304
+
305
+ describe "initial_state" do
306
+
307
+ it "should set the initial state to its argument, creating if it does not exist" do
308
+ @machine.instance_eval do
309
+ class << self
310
+ attr_accessor :initial_state
311
+ end
312
+ end
313
+ @machine.states.should be_empty
314
+ @lathe.initial_state :bambi
315
+ @machine.states.should_not be_empty
316
+ @machine.states.length.should == 1
317
+ @machine.states.first.name.should == :bambi
318
+ @machine.initial_state.name.should == :bambi
319
+ @lathe.initial_state :thumper
320
+ @machine.states.length.should == 2
321
+ @machine.states.map(&:name).should == [:bambi, :thumper]
322
+ @machine.states.last.name.should == :thumper
323
+ @machine.initial_state.name.should == :thumper
324
+ end
325
+ end
326
+
327
+ describe "helper" do
328
+ it "should call machine.helper *args" do
329
+ mock( @machine ).helper( :fee, :fi, :fo, :fum )
330
+ @lathe.helper( :fee, :fi, :fo, :fum )
331
+ end
332
+ end
333
+
334
+ end # master lathe instance
335
+
336
+ # child lathe - created and yielded within nested blocks in a
337
+ # machine definition
338
+ describe "a child lathe for a state" do
339
+ before do
340
+ @master = @lathe
341
+ @state = @lathe.state(:a)
342
+ @lathe = StateFu::Lathe.new( @machine, @state )
343
+ end
344
+
345
+ describe ".cycle( evt_name )" do
346
+ before do
347
+ @machine = StateFu::Machine.new( :snoo )
348
+ @master = StateFu::Lathe.new( @machine )
349
+ @state = @master.state(:a)
350
+ @lathe = StateFu::Lathe.new( @machine, @state )
351
+ end
352
+
353
+ it "should create a named event from and to the lathe's sprocket (state)" do
354
+
355
+ @machine.events.should be_empty
356
+ @machine.states.length.should == 1
357
+ @lathe.cycle(:rebirth)
358
+ @machine.events.should_not be_empty
359
+ @machine.states.length.should == 1
360
+ cycle = @machine.events.first
361
+ cycle.should be_kind_of( StateFu::Event )
362
+ cycle.origins.should == [@state]
363
+ cycle.targets.should == [@state]
364
+ end
365
+
366
+ it "should create an event with a default name if given no name" do
367
+ @machine.events.should be_empty
368
+ @machine.states.length.should == 1
369
+ @lathe.cycle
370
+ @machine.events.should_not be_empty
371
+ @machine.states.length.should == 1
372
+ e = @machine.events.first
373
+ e.name.should == :cycle_a
374
+ e.origins.should == [@state]
375
+ e.targets.should == [@state]
376
+ end
377
+
378
+ end
379
+
380
+ describe ".event(:name)" do
381
+ before do
382
+ mock( @machine ).find_or_create_states_by_name( @lathe.sprocket ) { @lathe.sprocket }
383
+ end
384
+
385
+ it "should create the named event if it does not exist" do
386
+ @machine.events.should be_empty
387
+ @lathe.event(:poop)
388
+ @machine.events.should_not be_empty
389
+ @machine.events[:poop].should be_kind_of( StateFu::Event )
390
+ end
391
+
392
+ it "should update the named event if it does exist" do
393
+ @lathe.machine.should == @machine
394
+ @lathe.event(:poop)
395
+ @machine.events[:poop].options.should == {}
396
+ @lathe.event(:poop, :lick => :me )
397
+ @machine.events[:poop].options[:lick].should == :me
398
+ end
399
+
400
+ it "should yield a created event given a block with arity 1" do
401
+ @machine.events.length.should == 0
402
+ @lathe.event(:poop) do |e| # yield the event
403
+ e.should be_kind_of( StateFu::Event )
404
+ e.name.should == :poop
405
+ e.options[:called] = true
406
+ end
407
+ @machine.events.length.should == 1
408
+ e = @machine.events[:poop]
409
+ e.options[:called].should == true
410
+ end
411
+
412
+ end
413
+
414
+ describe ".requires()" do
415
+
416
+ before do
417
+ @state.exit_requirements.should == []
418
+ @state.entry_requirements.should == []
419
+ end
420
+
421
+ it "should add :method_name to state.entry_requirements given a name" do
422
+ @lathe.requires( :method_name )
423
+ @state.entry_requirements.should == [:method_name]
424
+ @state.exit_requirements.should == []
425
+ end
426
+
427
+
428
+ it "should add :method_name to state.entry_requirements given a name and :on => :exit" do
429
+ @lathe.requires( :method_name, :on => :exit )
430
+ @state.exit_requirements.should == [:method_name]
431
+ @state.entry_requirements.should == []
432
+ end
433
+
434
+ it "should add :method_name to entry_requirements and exit_requirements given a name and :on => [:entry, :exit]" do
435
+ @lathe.requires( :method_name, :on => [:entry, :exit] )
436
+ @state.exit_requirements.should == [:method_name]
437
+ @state.entry_requirements.should == [:method_name]
438
+ end
439
+
440
+ it "should add multiple method_names if more than one is given" do
441
+ @lathe.requires( :method_one, :method_two )
442
+ @lathe.requires( :method_three, :method_four, :on => [:exit] )
443
+ @state.entry_requirements.should == [:method_one, :method_two]
444
+ @state.exit_requirements.should == [:method_three, :method_four]
445
+ end
446
+
447
+ it "should add to machine.named_procs if a block is given" do
448
+ class << @machine
449
+ attr_accessor :named_procs
450
+ end
451
+ @machine.named_procs = {}
452
+ block = lambda { puts "wee" }
453
+ @machine.named_procs.should == {}
454
+ @lathe.requires( :method_name, :on => [:entry, :exit], &block )
455
+ @state.exit_requirements.should == [:method_name]
456
+ @state.entry_requirements.should == [:method_name]
457
+ @machine.named_procs[:method_name].should == block
458
+ end
459
+
460
+ it "should add a message to machine.requirement_messages if a string is given" do
461
+ class << @machine
462
+ attr_accessor :requirement_messages
463
+ end
464
+ @machine.requirement_messages = {}
465
+ @lathe.requires( :method_one, :message => "Method one says no soup for you!" )
466
+ @machine.should respond_to(:requirement_messages)
467
+ @machine.requirement_messages.keys.should == [:method_one]
468
+ @machine.requirement_messages.values.first.should be_kind_of( String )
469
+ end
470
+
471
+ end
472
+ end
473
+
474
+ describe "a child lathe for an event" do
475
+ before do
476
+ stub( @machine ).find_or_create_states_by_name(:a) { [:a] }
477
+ stub( @machine ).find_or_create_states_by_name(:b) { [:b] }
478
+
479
+ @master = @lathe
480
+ @event = @lathe.event( :go )
481
+ @lathe = StateFu::Lathe.new( @machine, @event )
482
+ end
483
+
484
+ describe ".from" do
485
+ it "should create any states mentioned which do not exist" do
486
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
487
+ @lathe.from( :a, :b )
488
+ end
489
+
490
+ it "should set the origins to the result of machine.find_or_create_states_by_name" do
491
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
492
+ @lathe.from( :a, :b )
493
+ @event.origins.should == [:a, :b]
494
+ end
495
+
496
+ it "should update @origins on successive invocations" do
497
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
498
+ mock( @machine ).find_or_create_states_by_name(:x, :y) { [:x, :y] }
499
+ @lathe.from( :a, :b )
500
+ @event.origins.should == [:a, :b]
501
+ @lathe.from( :x, :y )
502
+ @event.origins.should == [:x, :y]
503
+ end
504
+
505
+ it "should set both origin and target if a hash is given" do
506
+ mock( @machine ).find_or_create_states_by_name(:a) { [:a] }
507
+ mock( @machine ).find_or_create_states_by_name(:b) { [:b] }
508
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
509
+ mock( @machine ).find_or_create_states_by_name(:x, :y) { [:x, :y] }
510
+ @lathe.from( :a => :b )
511
+ @event.origin.should == :a
512
+ @event.target.should == :b
513
+ @lathe.from([:a, :b] => [:x, :y] )
514
+ @event.origins.should == [:a, :b]
515
+ @event.targets.should == [:x, :y]
516
+ end
517
+ end
518
+
519
+ describe ".to" do
520
+ it "should create any states mentioned which do not exist" do
521
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
522
+ @lathe.to( :a, :b )
523
+ end
524
+
525
+ it "should set the targets to the result of machine.find_or_create_states_by_name" do
526
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
527
+ @lathe.to( :a, :b )
528
+ @event.targets.should == [:a, :b]
529
+ end
530
+
531
+ it "should update @origins on successive invocations" do
532
+ mock( @machine ).find_or_create_states_by_name(:a, :b) { [:a, :b] }
533
+ mock( @machine ).find_or_create_states_by_name(:x, :y) { [:x, :y] }
534
+ @lathe.to( :a, :b )
535
+ @event.targets.should == [:a, :b]
536
+ @lathe.to( :x, :y )
537
+ @event.targets.should == [:x, :y]
538
+ end
539
+ end
540
+
541
+ describe ".requires()" do
542
+
543
+ before do
544
+ @event.requirements.should == []
545
+ end
546
+
547
+ it "should add :method_name to event.requirements given a name" do
548
+ @lathe.requires( :method_name )
549
+ @event.requirements.should == [:method_name]
550
+ end
551
+
552
+ it "should add to machine.named_procs if a block is given" do
553
+ class << @machine
554
+ attr_accessor :named_procs
555
+ end
556
+ @machine.named_procs = {}
557
+ block = lambda { puts "wee" }
558
+ @machine.named_procs.should == {}
559
+ @lathe.requires( :method_name, &block )
560
+ @event.requirements.should == [:method_name]
561
+ @machine.named_procs[:method_name].should == block
562
+ end
563
+
564
+ end # requires
565
+
566
+ end # ?
567
+ end