state_machine 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +8 -0
- data/Rakefile +1 -1
- data/lib/state_machine/initializers/rails.rb +5 -1
- data/lib/state_machine/integrations/active_record.rb +2 -2
- data/lib/state_machine/integrations/mongo_mapper.rb +2 -2
- data/lib/state_machine/integrations/mongoid.rb +2 -2
- data/lib/state_machine/integrations/sequel/versions.rb +4 -0
- data/lib/state_machine/integrations/sequel.rb +28 -2
- data/lib/state_machine/machine.rb +60 -15
- data/lib/state_machine/state.rb +4 -12
- data/test/unit/event_test.rb +77 -14
- data/test/unit/integrations/sequel_test.rb +15 -3
- data/test/unit/machine_test.rb +398 -29
- data/test/unit/state_test.rb +36 -7
- data/test/unit/transition_test.rb +1 -1
- metadata +20 -39
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
== master
|
2
2
|
|
3
|
+
== 1.0.1 / 2011-05-30
|
4
|
+
|
5
|
+
* Add the ability to ignore method conflicts for helpers
|
6
|
+
* Generate warnings for any helper, not just state helpers, that has a conflicting method defined in the class
|
7
|
+
* Fix scopes in Sequel not working if the table name contains double underscores or is not a string/symbol
|
8
|
+
* Add full support for chaining state scopes within Sequel integrations
|
9
|
+
* Fix Rails 3.1 deprecation warnings for configuring engine locales [Stefan Penner]
|
10
|
+
|
3
11
|
== 1.0.0 / 2011-05-12
|
4
12
|
|
5
13
|
* Celebrate
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'rake/gempackagetask'
|
|
6
6
|
|
7
7
|
spec = Gem::Specification.new do |s|
|
8
8
|
s.name = 'state_machine'
|
9
|
-
s.version = '1.0.
|
9
|
+
s.version = '1.0.1'
|
10
10
|
s.platform = Gem::Platform::RUBY
|
11
11
|
s.summary = 'Adds support for creating state machines for attributes on any Ruby class'
|
12
12
|
s.description = s.summary
|
@@ -13,7 +13,11 @@ if defined?(Rails)
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
|
16
|
+
if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0
|
17
|
+
StateMachine::RailsEngine.paths.config.locales = locale_paths
|
18
|
+
else
|
19
|
+
StateMachine::RailsEngine.paths['config/locales'] = locale_paths
|
20
|
+
end
|
17
21
|
elsif defined?(I18n)
|
18
22
|
# Rails 2.x
|
19
23
|
I18n.load_path.unshift(*locale_paths)
|
@@ -416,8 +416,8 @@ module StateMachine
|
|
416
416
|
# ActiveModel's use of method_missing / respond_to for attribute methods
|
417
417
|
# breaks both ancestor lookups and defined?(super). Need to special-case
|
418
418
|
# the existence of query attribute methods.
|
419
|
-
def owner_class_ancestor_has_method?(method)
|
420
|
-
method == "#{name}?" || super
|
419
|
+
def owner_class_ancestor_has_method?(scope, method)
|
420
|
+
scope == :instance && method == "#{name}?" || super
|
421
421
|
end
|
422
422
|
end
|
423
423
|
end
|
@@ -264,8 +264,8 @@ module StateMachine
|
|
264
264
|
# ActiveModel's use of method_missing / respond_to for attribute methods
|
265
265
|
# breaks both ancestor lookups and defined?(super). Need to special-case
|
266
266
|
# the existence of query attribute methods.
|
267
|
-
def owner_class_ancestor_has_method?(method)
|
268
|
-
method == "#{name}?" || super
|
267
|
+
def owner_class_ancestor_has_method?(scope, method)
|
268
|
+
scope == :instance && method == "#{name}?" || super
|
269
269
|
end
|
270
270
|
end
|
271
271
|
end
|
@@ -349,8 +349,8 @@ module StateMachine
|
|
349
349
|
# ActiveModel's use of method_missing / respond_to for attribute methods
|
350
350
|
# breaks both ancestor lookups and defined?(super). Need to special-case
|
351
351
|
# the existence of query attribute methods.
|
352
|
-
def owner_class_ancestor_has_method?(method)
|
353
|
-
method == "#{name}?" || super
|
352
|
+
def owner_class_ancestor_has_method?(scope, method)
|
353
|
+
scope == :instance && method == "#{name}?" || super
|
354
354
|
end
|
355
355
|
end
|
356
356
|
end
|
@@ -374,13 +374,39 @@ module StateMachine
|
|
374
374
|
# Creates a scope for finding records *with* a particular state or
|
375
375
|
# states for the attribute
|
376
376
|
def create_with_scope(name)
|
377
|
-
lambda {|
|
377
|
+
create_scope(name, lambda {|dataset, values| dataset.filter(attribute_column => values)})
|
378
378
|
end
|
379
379
|
|
380
380
|
# Creates a scope for finding records *without* a particular state or
|
381
381
|
# states for the attribute
|
382
382
|
def create_without_scope(name)
|
383
|
-
lambda {|
|
383
|
+
create_scope(name, lambda {|dataset, values| dataset.exclude(attribute_column => values)})
|
384
|
+
end
|
385
|
+
|
386
|
+
# Creates a new named scope with the given name
|
387
|
+
def create_scope(name, scope)
|
388
|
+
machine = self
|
389
|
+
owner_class.def_dataset_method(name) do |*states|
|
390
|
+
machine.send(:run_scope, scope, self, states)
|
391
|
+
end
|
392
|
+
|
393
|
+
false
|
394
|
+
end
|
395
|
+
|
396
|
+
# Generates the results for the given scope based on one or more states to
|
397
|
+
# filter by
|
398
|
+
def run_scope(scope, dataset, states)
|
399
|
+
super(scope, model_from_dataset(dataset).state_machine(name), dataset, states)
|
400
|
+
end
|
401
|
+
|
402
|
+
# Determines the model associated with the given dataset
|
403
|
+
def model_from_dataset(dataset)
|
404
|
+
dataset.model
|
405
|
+
end
|
406
|
+
|
407
|
+
# Generates the fully-qualifed column name for this machine's attribute
|
408
|
+
def attribute_column
|
409
|
+
::Sequel::SQL::QualifiedIdentifier.new(owner_class.table_name, attribute)
|
384
410
|
end
|
385
411
|
|
386
412
|
# Runs a new database transaction, rolling back any changes if the
|
@@ -376,6 +376,11 @@ module StateMachine
|
|
376
376
|
:invalid_transition => 'cannot transition via "%s"'
|
377
377
|
}
|
378
378
|
|
379
|
+
# Whether to ignore any conflicts that are detected for helper methods that
|
380
|
+
# get generated for a machine's owner class. Default is false.
|
381
|
+
class << self; attr_accessor :ignore_method_conflicts; end
|
382
|
+
@ignore_method_conflicts = false
|
383
|
+
|
379
384
|
# The class that the machine is defined in
|
380
385
|
attr_accessor :owner_class
|
381
386
|
|
@@ -583,6 +588,11 @@ module StateMachine
|
|
583
588
|
# name. If the method is already defined in the scope, then this will not
|
584
589
|
# override it.
|
585
590
|
#
|
591
|
+
# If passing in a block, there are two side effects to be aware of
|
592
|
+
# 1. The method cannot be chained, meaning that the block cannot call +super+
|
593
|
+
# 2. If the method is already defined in an ancestor, then it will not get
|
594
|
+
# overridden and a warning will be output.
|
595
|
+
#
|
586
596
|
# Example:
|
587
597
|
#
|
588
598
|
# # Instance helper
|
@@ -611,15 +621,22 @@ module StateMachine
|
|
611
621
|
# end
|
612
622
|
# end_eval
|
613
623
|
def define_helper(scope, method, *args, &block)
|
624
|
+
helper_module = @helper_modules.fetch(scope)
|
625
|
+
|
614
626
|
if block_given?
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
627
|
+
if !self.class.ignore_method_conflicts && conflicting_ancestor = owner_class_ancestor_has_method?(scope, method)
|
628
|
+
ancestor_name = conflicting_ancestor.name && !conflicting_ancestor.name.empty? ? conflicting_ancestor.name : conflicting_ancestor.to_s
|
629
|
+
warn "#{scope == :class ? 'Class' : 'Instance'} method \"#{method}\" is already defined in #{ancestor_name}, use generic helper instead."
|
630
|
+
else
|
631
|
+
name = self.name
|
632
|
+
helper_module.class_eval do
|
633
|
+
define_method(method) do |*args|
|
634
|
+
block.call((scope == :instance ? self.class : self).state_machine(name), self, *args)
|
635
|
+
end
|
619
636
|
end
|
620
637
|
end
|
621
638
|
else
|
622
|
-
|
639
|
+
helper_module.class_eval(method, *args)
|
623
640
|
end
|
624
641
|
end
|
625
642
|
|
@@ -1585,13 +1602,14 @@ module StateMachine
|
|
1585
1602
|
def define_state_accessor
|
1586
1603
|
attribute = self.attribute
|
1587
1604
|
|
1588
|
-
@helper_modules[:instance].class_eval {
|
1605
|
+
@helper_modules[:instance].class_eval { attr_reader attribute } unless owner_class_ancestor_has_method?(:instance, attribute)
|
1606
|
+
@helper_modules[:instance].class_eval { attr_writer attribute } unless owner_class_ancestor_has_method?(:instance, "#{attribute}=")
|
1589
1607
|
end
|
1590
1608
|
|
1591
1609
|
# Adds predicate method to the owner class for determining the name of the
|
1592
1610
|
# current state
|
1593
1611
|
def define_state_predicate
|
1594
|
-
call_super = owner_class_ancestor_has_method?("#{name}?")
|
1612
|
+
call_super = !!owner_class_ancestor_has_method?(:instance, "#{name}?")
|
1595
1613
|
define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
|
1596
1614
|
def #{name}?(*args)
|
1597
1615
|
args.empty? && #{call_super} ? super : self.class.state_machine(#{name.inspect}).states.matches?(self, *args)
|
@@ -1686,14 +1704,35 @@ module StateMachine
|
|
1686
1704
|
# action must be defined in an ancestor of the owner classs in order for
|
1687
1705
|
# it to be the action hook.
|
1688
1706
|
def action_hook
|
1689
|
-
action && owner_class_ancestor_has_method?(action) ? action : nil
|
1707
|
+
action && owner_class_ancestor_has_method?(:instance, action) ? action : nil
|
1690
1708
|
end
|
1691
1709
|
|
1692
|
-
# Determines whether
|
1693
|
-
#
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1710
|
+
# Determines whether there's already a helper method defined within the
|
1711
|
+
# given scope. This is true only if one of the owner's ancestors defines
|
1712
|
+
# the method and is further along in the ancestor chain than this
|
1713
|
+
# machine's helper module.
|
1714
|
+
def owner_class_ancestor_has_method?(scope, method)
|
1715
|
+
superclasses = owner_class.ancestors[1..-1].select {|ancestor| ancestor.is_a?(Class)}
|
1716
|
+
|
1717
|
+
if scope == :class
|
1718
|
+
# Use singleton classes
|
1719
|
+
current = (class << owner_class; self; end)
|
1720
|
+
superclass = superclasses.first
|
1721
|
+
else
|
1722
|
+
current = owner_class
|
1723
|
+
superclass = owner_class.superclass
|
1724
|
+
end
|
1725
|
+
|
1726
|
+
# Generate the list of modules that *only* occur in the owner class, but
|
1727
|
+
# were included *prior* to the helper modules, in addition to the
|
1728
|
+
# superclasses
|
1729
|
+
ancestors = current.ancestors - superclass.ancestors + superclasses
|
1730
|
+
ancestors = ancestors[ancestors.index(@helper_modules[scope]) + 1..-1].reverse
|
1731
|
+
|
1732
|
+
# Search for for the first ancestor that defined this method
|
1733
|
+
ancestors.detect do |ancestor|
|
1734
|
+
ancestor = (class << ancestor; self; end) if scope == :class && ancestor.is_a?(Class)
|
1735
|
+
ancestor.method_defined?(method) || ancestor.private_method_defined?(method)
|
1697
1736
|
end
|
1698
1737
|
end
|
1699
1738
|
|
@@ -1737,14 +1776,20 @@ module StateMachine
|
|
1737
1776
|
# Converts state names to their corresponding values so that they
|
1738
1777
|
# can be looked up properly
|
1739
1778
|
define_helper(:class, method) do |machine, klass, *states|
|
1740
|
-
|
1741
|
-
scope.call(klass, values)
|
1779
|
+
run_scope(scope, machine, klass, states)
|
1742
1780
|
end
|
1743
1781
|
end
|
1744
1782
|
end
|
1745
1783
|
end
|
1746
1784
|
end
|
1747
1785
|
|
1786
|
+
# Generates the results for the given scope based on one or more states to
|
1787
|
+
# filter by
|
1788
|
+
def run_scope(scope, machine, klass, states)
|
1789
|
+
values = states.flatten.map {|state| machine.states.fetch(state).value}
|
1790
|
+
scope.call(klass, values)
|
1791
|
+
end
|
1792
|
+
|
1748
1793
|
# Pluralizes the given word using #pluralize (if available) or simply
|
1749
1794
|
# adding an "s" to the end of the word
|
1750
1795
|
def pluralize(word)
|
data/lib/state_machine/state.rb
CHANGED
@@ -260,19 +260,11 @@ module StateMachine
|
|
260
260
|
end
|
261
261
|
|
262
262
|
# Adds a predicate method to the owner class so long as a name has
|
263
|
-
# actually been configured for the state
|
264
|
-
# defined in the owner class.
|
263
|
+
# actually been configured for the state
|
265
264
|
def add_predicate
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
# Checks whether the current value matches this state
|
270
|
-
machine.define_helper(:instance, predicate) do |machine, object|
|
271
|
-
machine.states.matches?(object, name)
|
272
|
-
end
|
273
|
-
else
|
274
|
-
# Only output a warning since we can't defined the predicate
|
275
|
-
warn "#{owner_class.name}##{predicate} is already defined, use #{owner_class.name}##{machine.name}?(:#{name}) instead."
|
265
|
+
# Checks whether the current value matches this state
|
266
|
+
machine.define_helper(:instance, "#{qualified_name}?") do |machine, object|
|
267
|
+
machine.states.matches?(object, name)
|
276
268
|
end
|
277
269
|
end
|
278
270
|
end
|
data/test/unit/event_test.rb
CHANGED
@@ -127,8 +127,68 @@ class EventWithDynamicHumanNameTest < Test::Unit::TestCase
|
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
class
|
130
|
+
class EventWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
|
131
131
|
def setup
|
132
|
+
require 'stringio'
|
133
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
134
|
+
|
135
|
+
@superclass = Class.new do
|
136
|
+
def can_ignite?
|
137
|
+
0
|
138
|
+
end
|
139
|
+
|
140
|
+
def ignite_transition
|
141
|
+
0
|
142
|
+
end
|
143
|
+
|
144
|
+
def ignite
|
145
|
+
0
|
146
|
+
end
|
147
|
+
|
148
|
+
def ignite!
|
149
|
+
0
|
150
|
+
end
|
151
|
+
end
|
152
|
+
@klass = Class.new(@superclass)
|
153
|
+
@machine = StateMachine::Machine.new(@klass)
|
154
|
+
@machine.events << @event = StateMachine::Event.new(@machine, :ignite)
|
155
|
+
@object = @klass.new
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_should_not_redefine_predicate
|
159
|
+
assert_equal 0, @object.can_ignite?
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_should_not_redefine_transition_accessor
|
163
|
+
assert_equal 0, @object.ignite_transition
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_should_not_redefine_action
|
167
|
+
assert_equal 0, @object.ignite
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_should_not_redefine_bang_action
|
171
|
+
assert_equal 0, @object.ignite!
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_should_output_warning
|
175
|
+
expected = %w(can_ignite? ignite_transition ignite ignite!).map do |method|
|
176
|
+
"Instance method \"#{method}\" is already defined in #{@superclass.to_s}, use generic helper instead.\n"
|
177
|
+
end.join
|
178
|
+
|
179
|
+
assert_equal expected, $stderr.string
|
180
|
+
end
|
181
|
+
|
182
|
+
def teardown
|
183
|
+
$stderr = @original_stderr
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class EventWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
|
188
|
+
def setup
|
189
|
+
require 'stringio'
|
190
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
191
|
+
|
132
192
|
@klass = Class.new do
|
133
193
|
def can_ignite?
|
134
194
|
0
|
@@ -170,31 +230,34 @@ class EventWithConflictingHelpersTest < Test::Unit::TestCase
|
|
170
230
|
def test_should_allow_super_chaining
|
171
231
|
@klass.class_eval do
|
172
232
|
def can_ignite?
|
173
|
-
super
|
233
|
+
super
|
174
234
|
end
|
175
235
|
|
176
236
|
def ignite_transition
|
177
|
-
super
|
237
|
+
super
|
178
238
|
end
|
179
239
|
|
180
240
|
def ignite
|
181
|
-
super
|
241
|
+
super
|
182
242
|
end
|
183
243
|
|
184
244
|
def ignite!
|
185
|
-
|
186
|
-
super
|
187
|
-
1
|
188
|
-
rescue Exception => ex
|
189
|
-
0
|
190
|
-
end
|
245
|
+
super
|
191
246
|
end
|
192
247
|
end
|
193
248
|
|
194
|
-
assert_equal
|
195
|
-
assert_equal
|
196
|
-
assert_equal
|
197
|
-
|
249
|
+
assert_equal false, @object.can_ignite?
|
250
|
+
assert_equal nil, @object.ignite_transition
|
251
|
+
assert_equal false, @object.ignite
|
252
|
+
assert_raise(StateMachine::InvalidTransition) { @object.ignite! }
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_should_not_output_warning
|
256
|
+
assert_equal '', $stderr.string
|
257
|
+
end
|
258
|
+
|
259
|
+
def teardown
|
260
|
+
$stderr = @original_stderr
|
198
261
|
end
|
199
262
|
end
|
200
263
|
|
@@ -20,11 +20,11 @@ module SequelTest
|
|
20
20
|
def new_model(create_table = :foo, &block)
|
21
21
|
table_name = create_table || :foo
|
22
22
|
|
23
|
-
DB.create_table!(table_name) do
|
23
|
+
DB.create_table!(::Sequel::SQL::Identifier.new(table_name)) do
|
24
24
|
primary_key :id
|
25
25
|
column :state, :string
|
26
26
|
end if create_table
|
27
|
-
model = Class.new(Sequel::Model(table_name)) do
|
27
|
+
model = Class.new(Sequel::Model(DB[::Sequel::SQL::Identifier.new(table_name)])) do
|
28
28
|
self.raise_on_save_failure = false
|
29
29
|
(class << self; self; end).class_eval do
|
30
30
|
define_method(:name) { "SequelTest::#{table_name.to_s.capitalize}" }
|
@@ -1426,7 +1426,19 @@ module SequelTest
|
|
1426
1426
|
parked = @model.create :state => 'parked'
|
1427
1427
|
idling = @model.create :state => 'idling'
|
1428
1428
|
|
1429
|
-
assert_equal [idling], @model.without_state(:parked).
|
1429
|
+
assert_equal [idling], @model.without_state(:parked).with_state(:idling).all
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def test_should_run_on_tables_with_double_underscores
|
1433
|
+
@model = new_model(:foo__bar)
|
1434
|
+
@machine = StateMachine::Machine.new(@model)
|
1435
|
+
@machine.state :parked, :first_gear
|
1436
|
+
@machine.state :idling, :value => lambda {'idling'}
|
1437
|
+
|
1438
|
+
parked = @model.create :state => 'parked'
|
1439
|
+
idling = @model.create :state => 'idling'
|
1440
|
+
|
1441
|
+
assert_equal [parked], @model.with_state(:parked).all
|
1430
1442
|
end
|
1431
1443
|
end
|
1432
1444
|
|
data/test/unit/machine_test.rb
CHANGED
@@ -1114,6 +1114,104 @@ class MachineWithInstanceHelpersTest < Test::Unit::TestCase
|
|
1114
1114
|
assert_equal 'parked', @object.send(:state)
|
1115
1115
|
end
|
1116
1116
|
|
1117
|
+
def test_should_warn_if_defined_in_superclass
|
1118
|
+
require 'stringio'
|
1119
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1120
|
+
|
1121
|
+
superclass = Class.new do
|
1122
|
+
def park
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
klass = Class.new(superclass)
|
1126
|
+
machine = StateMachine::Machine.new(klass)
|
1127
|
+
|
1128
|
+
machine.define_helper(:instance, :park) {}
|
1129
|
+
assert_equal "Instance method \"park\" is already defined in #{superclass.to_s}, use generic helper instead.\n", $stderr.string
|
1130
|
+
ensure
|
1131
|
+
$stderr = @original_stderr
|
1132
|
+
end
|
1133
|
+
|
1134
|
+
def test_should_warn_if_defined_in_multiple_superclasses
|
1135
|
+
require 'stringio'
|
1136
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1137
|
+
|
1138
|
+
superclass1 = Class.new do
|
1139
|
+
def park
|
1140
|
+
end
|
1141
|
+
end
|
1142
|
+
superclass2 = Class.new(superclass1) do
|
1143
|
+
def park
|
1144
|
+
end
|
1145
|
+
end
|
1146
|
+
klass = Class.new(superclass2)
|
1147
|
+
machine = StateMachine::Machine.new(klass)
|
1148
|
+
|
1149
|
+
machine.define_helper(:instance, :park) {}
|
1150
|
+
assert_equal "Instance method \"park\" is already defined in #{superclass1.to_s}, use generic helper instead.\n", $stderr.string
|
1151
|
+
ensure
|
1152
|
+
$stderr = @original_stderr
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
def test_should_warn_if_defined_in_module_prior_to_helper_module
|
1156
|
+
require 'stringio'
|
1157
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1158
|
+
|
1159
|
+
mod = Module.new do
|
1160
|
+
def park
|
1161
|
+
end
|
1162
|
+
end
|
1163
|
+
klass = Class.new do
|
1164
|
+
include mod
|
1165
|
+
end
|
1166
|
+
machine = StateMachine::Machine.new(klass)
|
1167
|
+
|
1168
|
+
machine.define_helper(:instance, :park) {}
|
1169
|
+
assert_equal "Instance method \"park\" is already defined in #{mod.to_s}, use generic helper instead.\n", $stderr.string
|
1170
|
+
ensure
|
1171
|
+
$stderr = @original_stderr
|
1172
|
+
end
|
1173
|
+
|
1174
|
+
def test_should_not_warn_if_defined_in_module_after_helper_module
|
1175
|
+
require 'stringio'
|
1176
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1177
|
+
|
1178
|
+
klass = Class.new
|
1179
|
+
machine = StateMachine::Machine.new(klass)
|
1180
|
+
|
1181
|
+
mod = Module.new do
|
1182
|
+
def park
|
1183
|
+
end
|
1184
|
+
end
|
1185
|
+
klass.class_eval do
|
1186
|
+
include mod
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
machine.define_helper(:instance, :park) {}
|
1190
|
+
assert_equal '', $stderr.string
|
1191
|
+
ensure
|
1192
|
+
$stderr = @original_stderr
|
1193
|
+
end
|
1194
|
+
|
1195
|
+
def test_should_define_if_ignoring_method_conflicts_and_defined_in_superclass
|
1196
|
+
require 'stringio'
|
1197
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1198
|
+
StateMachine::Machine.ignore_method_conflicts = true
|
1199
|
+
|
1200
|
+
superclass = Class.new do
|
1201
|
+
def park
|
1202
|
+
end
|
1203
|
+
end
|
1204
|
+
klass = Class.new(superclass)
|
1205
|
+
machine = StateMachine::Machine.new(klass)
|
1206
|
+
|
1207
|
+
machine.define_helper(:instance, :park) {true}
|
1208
|
+
assert_equal '', $stderr.string
|
1209
|
+
assert_equal true, klass.new.park
|
1210
|
+
ensure
|
1211
|
+
StateMachine::Machine.ignore_method_conflicts = false
|
1212
|
+
$stderr = @original_stderr
|
1213
|
+
end
|
1214
|
+
|
1117
1215
|
def test_should_define_nonexistent_methods
|
1118
1216
|
@machine.define_helper(:instance, :state) {'parked'}
|
1119
1217
|
assert_equal 'parked', @object.state
|
@@ -1186,6 +1284,104 @@ class MachineWithClassHelpersTest < Test::Unit::TestCase
|
|
1186
1284
|
assert_equal [], @klass.send(:states)
|
1187
1285
|
end
|
1188
1286
|
|
1287
|
+
def test_should_warn_if_defined_in_superclass
|
1288
|
+
require 'stringio'
|
1289
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1290
|
+
|
1291
|
+
superclass = Class.new do
|
1292
|
+
def self.park
|
1293
|
+
end
|
1294
|
+
end
|
1295
|
+
klass = Class.new(superclass)
|
1296
|
+
machine = StateMachine::Machine.new(klass)
|
1297
|
+
|
1298
|
+
machine.define_helper(:class, :park) {}
|
1299
|
+
assert_equal "Class method \"park\" is already defined in #{superclass.to_s}, use generic helper instead.\n", $stderr.string
|
1300
|
+
ensure
|
1301
|
+
$stderr = @original_stderr
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
def test_should_warn_if_defined_in_multiple_superclasses
|
1305
|
+
require 'stringio'
|
1306
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1307
|
+
|
1308
|
+
superclass1 = Class.new do
|
1309
|
+
def self.park
|
1310
|
+
end
|
1311
|
+
end
|
1312
|
+
superclass2 = Class.new(superclass1) do
|
1313
|
+
def self.park
|
1314
|
+
end
|
1315
|
+
end
|
1316
|
+
klass = Class.new(superclass2)
|
1317
|
+
machine = StateMachine::Machine.new(klass)
|
1318
|
+
|
1319
|
+
machine.define_helper(:class, :park) {}
|
1320
|
+
assert_equal "Class method \"park\" is already defined in #{superclass1.to_s}, use generic helper instead.\n", $stderr.string
|
1321
|
+
ensure
|
1322
|
+
$stderr = @original_stderr
|
1323
|
+
end
|
1324
|
+
|
1325
|
+
def test_should_warn_if_defined_in_module_prior_to_helper_module
|
1326
|
+
require 'stringio'
|
1327
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1328
|
+
|
1329
|
+
mod = Module.new do
|
1330
|
+
def park
|
1331
|
+
end
|
1332
|
+
end
|
1333
|
+
klass = Class.new do
|
1334
|
+
extend mod
|
1335
|
+
end
|
1336
|
+
machine = StateMachine::Machine.new(klass)
|
1337
|
+
|
1338
|
+
machine.define_helper(:class, :park) {}
|
1339
|
+
assert_equal "Class method \"park\" is already defined in #{mod.to_s}, use generic helper instead.\n", $stderr.string
|
1340
|
+
ensure
|
1341
|
+
$stderr = @original_stderr
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
def test_should_not_warn_if_defined_in_module_after_helper_module
|
1345
|
+
require 'stringio'
|
1346
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1347
|
+
|
1348
|
+
klass = Class.new
|
1349
|
+
machine = StateMachine::Machine.new(klass)
|
1350
|
+
|
1351
|
+
mod = Module.new do
|
1352
|
+
def park
|
1353
|
+
end
|
1354
|
+
end
|
1355
|
+
klass.class_eval do
|
1356
|
+
extend mod
|
1357
|
+
end
|
1358
|
+
|
1359
|
+
machine.define_helper(:class, :park) {}
|
1360
|
+
assert_equal '', $stderr.string
|
1361
|
+
ensure
|
1362
|
+
$stderr = @original_stderr
|
1363
|
+
end
|
1364
|
+
|
1365
|
+
def test_should_define_if_ignoring_method_conflicts_and_defined_in_superclass
|
1366
|
+
require 'stringio'
|
1367
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1368
|
+
StateMachine::Machine.ignore_method_conflicts = true
|
1369
|
+
|
1370
|
+
superclass = Class.new do
|
1371
|
+
def self.park
|
1372
|
+
end
|
1373
|
+
end
|
1374
|
+
klass = Class.new(superclass)
|
1375
|
+
machine = StateMachine::Machine.new(klass)
|
1376
|
+
|
1377
|
+
machine.define_helper(:class, :park) {true}
|
1378
|
+
assert_equal '', $stderr.string
|
1379
|
+
assert_equal true, klass.park
|
1380
|
+
ensure
|
1381
|
+
StateMachine::Machine.ignore_method_conflicts = false
|
1382
|
+
$stderr = @original_stderr
|
1383
|
+
end
|
1384
|
+
|
1189
1385
|
def test_should_define_nonexistent_methods
|
1190
1386
|
@machine.define_helper(:class, :states) {[]}
|
1191
1387
|
assert_equal [], @klass.states
|
@@ -1217,8 +1413,176 @@ class MachineWithClassHelpersTest < Test::Unit::TestCase
|
|
1217
1413
|
end
|
1218
1414
|
end
|
1219
1415
|
|
1220
|
-
class
|
1416
|
+
class MachineWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
|
1417
|
+
def setup
|
1418
|
+
require 'stringio'
|
1419
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1420
|
+
|
1421
|
+
@superclass = Class.new do
|
1422
|
+
def self.with_state
|
1423
|
+
:with_state
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
def self.with_states
|
1427
|
+
:with_states
|
1428
|
+
end
|
1429
|
+
|
1430
|
+
def self.without_state
|
1431
|
+
:without_state
|
1432
|
+
end
|
1433
|
+
|
1434
|
+
def self.without_states
|
1435
|
+
:without_states
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
def self.human_state_name
|
1439
|
+
:human_state_name
|
1440
|
+
end
|
1441
|
+
|
1442
|
+
def self.human_state_event_name
|
1443
|
+
:human_state_event_name
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
attr_accessor :status
|
1447
|
+
|
1448
|
+
def state
|
1449
|
+
'parked'
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
def state=(value)
|
1453
|
+
self.status = value
|
1454
|
+
end
|
1455
|
+
|
1456
|
+
def state?
|
1457
|
+
true
|
1458
|
+
end
|
1459
|
+
|
1460
|
+
def state_name
|
1461
|
+
:parked
|
1462
|
+
end
|
1463
|
+
|
1464
|
+
def human_state_name
|
1465
|
+
'parked'
|
1466
|
+
end
|
1467
|
+
|
1468
|
+
def state_events
|
1469
|
+
[:ignite]
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
def state_transitions
|
1473
|
+
[{:parked => :idling}]
|
1474
|
+
end
|
1475
|
+
|
1476
|
+
def state_paths
|
1477
|
+
[[{:parked => :idling}]]
|
1478
|
+
end
|
1479
|
+
end
|
1480
|
+
@klass = Class.new(@superclass)
|
1481
|
+
|
1482
|
+
StateMachine::Integrations.const_set('Custom', Module.new do
|
1483
|
+
include StateMachine::Integrations::Base
|
1484
|
+
|
1485
|
+
def create_with_scope(name)
|
1486
|
+
lambda {|klass, values| []}
|
1487
|
+
end
|
1488
|
+
|
1489
|
+
def create_without_scope(name)
|
1490
|
+
lambda {|klass, values| []}
|
1491
|
+
end
|
1492
|
+
end)
|
1493
|
+
|
1494
|
+
@machine = StateMachine::Machine.new(@klass, :integration => :custom)
|
1495
|
+
@machine.state :parked, :idling
|
1496
|
+
@machine.event :ignite
|
1497
|
+
@object = @klass.new
|
1498
|
+
end
|
1499
|
+
|
1500
|
+
def test_should_not_redefine_singular_with_scope
|
1501
|
+
assert_equal :with_state, @klass.with_state
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
def test_should_not_redefine_plural_with_scope
|
1505
|
+
assert_equal :with_states, @klass.with_states
|
1506
|
+
end
|
1507
|
+
|
1508
|
+
def test_should_not_redefine_singular_without_scope
|
1509
|
+
assert_equal :without_state, @klass.without_state
|
1510
|
+
end
|
1511
|
+
|
1512
|
+
def test_should_not_redefine_plural_without_scope
|
1513
|
+
assert_equal :without_states, @klass.without_states
|
1514
|
+
end
|
1515
|
+
|
1516
|
+
def test_should_not_redefine_human_attribute_name_reader
|
1517
|
+
assert_equal :human_state_name, @klass.human_state_name
|
1518
|
+
end
|
1519
|
+
|
1520
|
+
def test_should_not_redefine_human_event_name_reader
|
1521
|
+
assert_equal :human_state_event_name, @klass.human_state_event_name
|
1522
|
+
end
|
1523
|
+
|
1524
|
+
def test_should_not_redefine_attribute_writer
|
1525
|
+
assert_equal 'parked', @object.state
|
1526
|
+
end
|
1527
|
+
|
1528
|
+
def test_should_not_redefine_attribute_writer
|
1529
|
+
@object.state = 'parked'
|
1530
|
+
assert_equal 'parked', @object.status
|
1531
|
+
end
|
1532
|
+
|
1533
|
+
def test_should_not_define_attribute_predicate
|
1534
|
+
assert @object.state?
|
1535
|
+
end
|
1536
|
+
|
1537
|
+
def test_should_not_redefine_attribute_name_reader
|
1538
|
+
assert_equal :parked, @object.state_name
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
def test_should_not_redefine_attribute_human_name_reader
|
1542
|
+
assert_equal 'parked', @object.human_state_name
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
def test_should_not_redefine_attribute_events_reader
|
1546
|
+
assert_equal [:ignite], @object.state_events
|
1547
|
+
end
|
1548
|
+
|
1549
|
+
def test_should_not_redefine_attribute_transitions_reader
|
1550
|
+
assert_equal [{:parked => :idling}], @object.state_transitions
|
1551
|
+
end
|
1552
|
+
|
1553
|
+
def test_should_not_redefine_attribute_paths_reader
|
1554
|
+
assert_equal [[{:parked => :idling}]], @object.state_paths
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
def test_should_output_warning
|
1558
|
+
expected = [
|
1559
|
+
'Instance method "state_events"',
|
1560
|
+
'Instance method "state_transitions"',
|
1561
|
+
'Instance method "state_paths"',
|
1562
|
+
'Class method "human_state_name"',
|
1563
|
+
'Class method "human_state_event_name"',
|
1564
|
+
'Instance method "state_name"',
|
1565
|
+
'Instance method "human_state_name"',
|
1566
|
+
'Class method "with_state"',
|
1567
|
+
'Class method "without_state"',
|
1568
|
+
'Class method "with_states"',
|
1569
|
+
'Class method "without_states"'
|
1570
|
+
].map {|method| "#{method} is already defined in #{@superclass.to_s}, use generic helper instead.\n"}.join
|
1571
|
+
|
1572
|
+
assert_equal expected, $stderr.string
|
1573
|
+
end
|
1574
|
+
|
1575
|
+
def teardown
|
1576
|
+
$stderr = @original_stderr
|
1577
|
+
StateMachine::Integrations.send(:remove_const, 'Custom')
|
1578
|
+
end
|
1579
|
+
end
|
1580
|
+
|
1581
|
+
class MachineWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
|
1221
1582
|
def setup
|
1583
|
+
require 'stringio'
|
1584
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
1585
|
+
|
1222
1586
|
@klass = Class.new do
|
1223
1587
|
def self.with_state
|
1224
1588
|
:with_state
|
@@ -1357,84 +1721,89 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
|
|
1357
1721
|
def test_should_allow_super_chaining
|
1358
1722
|
@klass.class_eval do
|
1359
1723
|
def self.with_state(*states)
|
1360
|
-
super
|
1724
|
+
super
|
1361
1725
|
end
|
1362
1726
|
|
1363
1727
|
def self.with_states(*states)
|
1364
|
-
super
|
1728
|
+
super
|
1365
1729
|
end
|
1366
1730
|
|
1367
1731
|
def self.without_state(*states)
|
1368
|
-
super
|
1732
|
+
super
|
1369
1733
|
end
|
1370
1734
|
|
1371
1735
|
def self.without_states(*states)
|
1372
|
-
super
|
1736
|
+
super
|
1373
1737
|
end
|
1374
1738
|
|
1375
1739
|
def self.human_state_name(state)
|
1376
|
-
super
|
1740
|
+
super
|
1377
1741
|
end
|
1378
1742
|
|
1379
1743
|
def self.human_state_event_name(event)
|
1380
|
-
super
|
1744
|
+
super
|
1381
1745
|
end
|
1382
1746
|
|
1383
1747
|
attr_accessor :status
|
1384
1748
|
|
1385
1749
|
def state
|
1386
|
-
super
|
1750
|
+
super
|
1387
1751
|
end
|
1388
1752
|
|
1389
1753
|
def state=(value)
|
1390
1754
|
super
|
1391
|
-
self.status = value
|
1392
1755
|
end
|
1393
1756
|
|
1394
1757
|
def state?(state)
|
1395
|
-
super
|
1758
|
+
super
|
1396
1759
|
end
|
1397
1760
|
|
1398
1761
|
def state_name
|
1399
|
-
super
|
1762
|
+
super
|
1400
1763
|
end
|
1401
1764
|
|
1402
1765
|
def human_state_name
|
1403
|
-
super
|
1766
|
+
super
|
1404
1767
|
end
|
1405
1768
|
|
1406
1769
|
def state_events
|
1407
|
-
super
|
1770
|
+
super
|
1408
1771
|
end
|
1409
1772
|
|
1410
1773
|
def state_transitions
|
1411
|
-
super
|
1774
|
+
super
|
1412
1775
|
end
|
1413
1776
|
|
1414
1777
|
def state_paths
|
1415
|
-
super
|
1778
|
+
super
|
1416
1779
|
end
|
1417
1780
|
end
|
1418
1781
|
|
1419
|
-
assert_equal
|
1420
|
-
assert_equal
|
1421
|
-
assert_equal
|
1422
|
-
assert_equal
|
1423
|
-
assert_equal
|
1424
|
-
assert_equal
|
1782
|
+
assert_equal [], @klass.with_state
|
1783
|
+
assert_equal [], @klass.with_states
|
1784
|
+
assert_equal [], @klass.without_state
|
1785
|
+
assert_equal [], @klass.without_states
|
1786
|
+
assert_equal 'parked', @klass.human_state_name(:parked)
|
1787
|
+
assert_equal 'ignite', @klass.human_state_event_name(:ignite)
|
1425
1788
|
|
1426
|
-
assert_equal
|
1789
|
+
assert_equal nil, @object.state
|
1427
1790
|
@object.state = 'idling'
|
1428
|
-
assert_equal 'idling', @object.
|
1429
|
-
assert_equal
|
1430
|
-
assert_equal
|
1431
|
-
assert_equal
|
1432
|
-
assert_equal
|
1433
|
-
assert_equal
|
1434
|
-
assert_equal
|
1791
|
+
assert_equal 'idling', @object.state
|
1792
|
+
assert_equal nil, @object.status
|
1793
|
+
assert_equal false, @object.state?(:parked)
|
1794
|
+
assert_equal :idling, @object.state_name
|
1795
|
+
assert_equal 'idling', @object.human_state_name
|
1796
|
+
assert_equal [], @object.state_events
|
1797
|
+
assert_equal [], @object.state_transitions
|
1798
|
+
assert_equal [], @object.state_paths
|
1799
|
+
end
|
1800
|
+
|
1801
|
+
def test_should_not_output_warning
|
1802
|
+
assert_equal '', $stderr.string
|
1435
1803
|
end
|
1436
1804
|
|
1437
1805
|
def teardown
|
1806
|
+
$stderr = @original_stderr
|
1438
1807
|
StateMachine::Integrations.send(:remove_const, 'Custom')
|
1439
1808
|
end
|
1440
1809
|
end
|
data/test/unit/state_test.rb
CHANGED
@@ -458,7 +458,36 @@ class StateNotFinalTest < Test::Unit::TestCase
|
|
458
458
|
end
|
459
459
|
end
|
460
460
|
|
461
|
-
class
|
461
|
+
class StateWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
|
462
|
+
def setup
|
463
|
+
require 'stringio'
|
464
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
465
|
+
|
466
|
+
@superclass = Class.new do
|
467
|
+
def parked?
|
468
|
+
0
|
469
|
+
end
|
470
|
+
end
|
471
|
+
@klass = Class.new(@superclass)
|
472
|
+
@machine = StateMachine::Machine.new(@klass)
|
473
|
+
@machine.state :parked
|
474
|
+
@object = @klass.new
|
475
|
+
end
|
476
|
+
|
477
|
+
def test_should_not_override_state_predicate
|
478
|
+
assert_equal 0, @object.parked?
|
479
|
+
end
|
480
|
+
|
481
|
+
def test_should_output_warning
|
482
|
+
assert_equal "Instance method \"parked?\" is already defined in #{@superclass.to_s}, use generic helper instead.\n", $stderr.string
|
483
|
+
end
|
484
|
+
|
485
|
+
def teardown
|
486
|
+
$stderr = @original_stderr
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
class StateWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
|
462
491
|
def setup
|
463
492
|
require 'stringio'
|
464
493
|
@original_stderr, $stderr = $stderr, StringIO.new
|
@@ -477,18 +506,18 @@ class StateWithConflictingHelpersTest < Test::Unit::TestCase
|
|
477
506
|
assert_equal 0, @object.parked?
|
478
507
|
end
|
479
508
|
|
480
|
-
def
|
509
|
+
def test_should_still_allow_super_chaining
|
481
510
|
@klass.class_eval do
|
482
511
|
def parked?
|
483
|
-
super
|
512
|
+
super
|
484
513
|
end
|
485
514
|
end
|
486
515
|
|
487
|
-
|
516
|
+
assert_equal false, @object.parked?
|
488
517
|
end
|
489
518
|
|
490
|
-
def
|
491
|
-
assert_equal
|
519
|
+
def test_should_not_output_warning
|
520
|
+
assert_equal '', $stderr.string
|
492
521
|
end
|
493
522
|
|
494
523
|
def teardown
|
@@ -496,7 +525,7 @@ class StateWithConflictingHelpersTest < Test::Unit::TestCase
|
|
496
525
|
end
|
497
526
|
end
|
498
527
|
|
499
|
-
class
|
528
|
+
class StateWithConflictingMachineTest < Test::Unit::TestCase
|
500
529
|
def setup
|
501
530
|
require 'stringio'
|
502
531
|
@original_stderr, $stderr = $stderr, StringIO.new
|
@@ -1508,7 +1508,7 @@ class TransitionEqualityTest < Test::Unit::TestCase
|
|
1508
1508
|
end
|
1509
1509
|
|
1510
1510
|
def test_should_not_be_equal_with_different_machines
|
1511
|
-
machine = StateMachine::Machine.new(@klass, :namespace => :other)
|
1511
|
+
machine = StateMachine::Machine.new(@klass, :status, :namespace => :other)
|
1512
1512
|
machine.state :parked, :idling
|
1513
1513
|
machine.event :ignite
|
1514
1514
|
transition = StateMachine::Transition.new(@object, machine, :ignite, :parked, :idling)
|
metadata
CHANGED
@@ -1,33 +1,23 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: state_machine
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 1
|
8
|
-
- 0
|
9
|
-
- 0
|
10
|
-
version: 1.0.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Aaron Pfeifer
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-05-12 00:00:00 -04:00
|
12
|
+
date: 2011-05-30 00:00:00.000000000 -04:00
|
19
13
|
default_executable:
|
20
14
|
dependencies: []
|
21
|
-
|
22
15
|
description: Adds support for creating state machines for attributes on any Ruby class
|
23
16
|
email: aaron@pluginaweek.org
|
24
17
|
executables: []
|
25
|
-
|
26
18
|
extensions: []
|
27
|
-
|
28
19
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
20
|
+
files:
|
31
21
|
- examples/car.rb
|
32
22
|
- examples/TrafficLight_state.png
|
33
23
|
- examples/vehicle.rb
|
@@ -138,38 +128,29 @@ files:
|
|
138
128
|
has_rdoc: true
|
139
129
|
homepage: http://www.pluginaweek.org
|
140
130
|
licenses: []
|
141
|
-
|
142
131
|
post_install_message:
|
143
132
|
rdoc_options: []
|
144
|
-
|
145
|
-
require_paths:
|
133
|
+
require_paths:
|
146
134
|
- lib
|
147
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
136
|
none: false
|
149
|
-
requirements:
|
150
|
-
- -
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
|
153
|
-
|
154
|
-
- 0
|
155
|
-
version: "0"
|
156
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
142
|
none: false
|
158
|
-
requirements:
|
159
|
-
- -
|
160
|
-
- !ruby/object:Gem::Version
|
161
|
-
|
162
|
-
segments:
|
163
|
-
- 0
|
164
|
-
version: "0"
|
143
|
+
requirements:
|
144
|
+
- - ! '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
165
147
|
requirements: []
|
166
|
-
|
167
148
|
rubyforge_project: pluginaweek
|
168
|
-
rubygems_version: 1.
|
149
|
+
rubygems_version: 1.6.2
|
169
150
|
signing_key:
|
170
151
|
specification_version: 3
|
171
152
|
summary: Adds support for creating state machines for attributes on any Ruby class
|
172
|
-
test_files:
|
153
|
+
test_files:
|
173
154
|
- test/unit/path_test.rb
|
174
155
|
- test/unit/condition_proxy_test.rb
|
175
156
|
- test/unit/state_machine_test.rb
|