omg-statelogic 1.0.2 → 1.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.
- data/CHANGELOG +7 -1
- data/README.rdoc +8 -1
- data/lib/statelogic/activerecord.rb +40 -10
- data/shoulda_macros/statelogic.rb +3 -2
- data/test/statelogic_test.rb +22 -36
- metadata +5 -4
data/CHANGELOG
CHANGED
@@ -1,2 +1,8 @@
|
|
1
|
-
|
1
|
+
1.1 - 2009-08-11
|
2
|
+
- adds finder methods in the form of find_all_#{state}(*args)
|
3
|
+
- adds named scope named after corresponding state
|
4
|
+
- no longer redefines existing methods with the same names, issues warnings instead
|
5
|
+
- forces state names to underscore notation when used as part of method/scope names
|
6
|
+
|
7
|
+
0.1.2 - 2009-01-10
|
2
8
|
- Support scoping arbitrary callbacks beyond ActiveRecord's
|
data/README.rdoc
CHANGED
@@ -12,6 +12,13 @@ consistency over merely formal... whatever...
|
|
12
12
|
- ???????
|
13
13
|
- PROFIT!!!11
|
14
14
|
|
15
|
+
=== Changes in v1.1
|
16
|
+
_Please review these carefully as they may be incompatible with your existing code._
|
17
|
+
- adds finder methods in the form of +find_all_#{state}(*args)+ (Order.find_all_ready) sugg. by ares
|
18
|
+
- adds named scope named after corresponding state (Order.paid) sugg. by ares
|
19
|
+
- no longer redefines existing methods with the same names, issues warnings instead
|
20
|
+
- forces state names to underscore notation when used as part of method names
|
21
|
+
|
15
22
|
=== Installation
|
16
23
|
gem install omg-statelogic --source http://gems.github.com
|
17
24
|
|
@@ -32,7 +39,7 @@ Please report via Github issue tracking.
|
|
32
39
|
initial_state 'unpaid' do
|
33
40
|
transitions_to 'ready', 'suspended' # won't let you change to wrong states
|
34
41
|
end
|
35
|
-
state 'ready' do # you get +ready?+, +was_ready
|
42
|
+
state 'ready' do # you get +ready?+, +was_ready?+, +Order.ready+ named scope and +Order.find_all_ready+ finder
|
36
43
|
transitions_to 'redeemed', 'suspended'
|
37
44
|
validates_presence_of :txref # scoped validations
|
38
45
|
before_save :prepare_for_plucking # scoped callbacks
|
@@ -1,6 +1,27 @@
|
|
1
|
-
require 'statelogic/callbacks_ext'
|
1
|
+
require 'statelogic/callbacks_ext' unless ([ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR] <=> [2, 3]) >= 0
|
2
2
|
|
3
3
|
module Statelogic
|
4
|
+
module Util
|
5
|
+
def self.debug(msg = nil, &block)
|
6
|
+
::ActiveRecord::Base.logger.debug(msg, &block) if ::ActiveRecord::Base.logger
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.warn(msg = nil, &block)
|
10
|
+
::ActiveRecord::Base.logger.warn(msg, &block) if ::ActiveRecord::Base.logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.defmethod(cls, name, meta = false, &block)
|
14
|
+
c = meta ? cls.metaclass : cls
|
15
|
+
unless c.method_defined?(name)
|
16
|
+
c.send(:define_method, name, &block)
|
17
|
+
Util.debug { "Statelogic created #{meta ? 'class' : 'instance'} method #{name} on #{cls.name}." }
|
18
|
+
else
|
19
|
+
warn { "Statelogic won't override #{meta ? 'class' : 'instance'} method #{name} already defined on #{cls.name}." }
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
4
25
|
module ActiveRecord
|
5
26
|
def self.included(other)
|
6
27
|
other.extend(ClassMethods)
|
@@ -51,14 +72,25 @@ module Statelogic
|
|
51
72
|
alias initial initial_state
|
52
73
|
|
53
74
|
def state(name, options = {}, &block)
|
75
|
+
name = name.to_s
|
76
|
+
uname = name.underscore
|
54
77
|
attr = @config[:attribute]
|
55
78
|
attr_was = :"#{attr}_was"
|
56
|
-
|
57
|
-
|
58
|
-
|
79
|
+
find_all_by_attr = "find_all_by_#{attr}"
|
80
|
+
|
81
|
+
Util.defmethod(@class, "#{uname}?") { send(attr) == name }
|
82
|
+
Util.defmethod(@class, "was_#{uname}?") { send(attr_was) == name }
|
83
|
+
|
84
|
+
unless @class.respond_to?(name)
|
85
|
+
@class.send(:named_scope, uname, :conditions => {attr.to_sym => name })
|
86
|
+
Util.debug { "Statelogic has defined named scope #{uname} on #{@class.name}." }
|
87
|
+
else
|
88
|
+
Util.warn { "Statelogic won't override class method #{uname} already defined on #{@class.name}." }
|
59
89
|
end
|
60
90
|
|
61
|
-
|
91
|
+
Util.defmethod(@class, "find_all_#{uname}", true) {|*args| send(find_all_by_attr, name, *args) }
|
92
|
+
|
93
|
+
StateScopeHelper.new(@class, name, @config).instance_eval(&block) if block_given?
|
62
94
|
|
63
95
|
@config[:states] << name
|
64
96
|
@config[:initial] << name if options[:initial]
|
@@ -73,7 +105,7 @@ module Statelogic
|
|
73
105
|
|
74
106
|
ConfigHelper.new(self, options).instance_eval(&block)
|
75
107
|
|
76
|
-
initial = [options[:initial], options[:states]].find
|
108
|
+
initial = [options[:initial], options[:states]].find(&:present?)
|
77
109
|
validates_inclusion_of attr, :in => initial, :on => :create if initial
|
78
110
|
|
79
111
|
const = attr.to_s.pluralize.upcase
|
@@ -83,7 +115,5 @@ module Statelogic
|
|
83
115
|
end
|
84
116
|
end
|
85
117
|
|
86
|
-
|
87
|
-
|
88
|
-
include Statelogic::ActiveRecord
|
89
|
-
end
|
118
|
+
ActiveRecord::Base.send :include, Statelogic::ActiveRecord
|
119
|
+
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Test::Unit::TestCase
|
2
2
|
def self.should_not_require_attributes(*attributes)
|
3
3
|
get_options!(attributes)
|
4
|
-
klass =
|
4
|
+
klass = described_type
|
5
5
|
|
6
6
|
attributes.each do |attribute|
|
7
7
|
should "not require #{attribute} to be set" do
|
@@ -9,4 +9,5 @@ class Test::Unit::TestCase
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
|
-
end
|
12
|
+
end
|
13
|
+
|
data/test/statelogic_test.rb
CHANGED
@@ -1,39 +1,32 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
statelogic do
|
5
|
-
initial_state 'unpaid' do
|
6
|
-
transitions_to 'ready', 'suspended'
|
7
|
-
end
|
8
|
-
state 'ready' do
|
9
|
-
transitions_to 'redeemed', 'suspended'
|
10
|
-
validates_presence_of :txref
|
11
|
-
end
|
12
|
-
state 'redeemed' do
|
13
|
-
transitions_to 'suspended'
|
14
|
-
validates_presence_of :txref, :redeemed_at, :facility_id
|
15
|
-
end
|
16
|
-
state 'suspended' do
|
17
|
-
transitions_to 'unpaid', 'ready', 'redeemed'
|
18
|
-
validate do |order|
|
19
|
-
order.errors.add(:txref, :invalid) if order.txref && order.txref !~ /\AREF/
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
3
|
+
#ActiveRecord::Base.logger = Logger.new(STDERR)
|
24
4
|
|
25
5
|
class OrderTest < ActiveSupport::TestCase
|
26
6
|
include ActiveRecord::TestFixtures
|
27
7
|
self.fixture_path = 'test/fixtures'
|
28
8
|
|
29
9
|
fixtures :orders
|
10
|
+
|
11
|
+
should_have_class_methods :unpaid, :ready, :redeemed, :suspended
|
12
|
+
should_have_class_methods :find_all_unpaid, :find_all_ready, :find_all_redeemed, :find_all_suspended
|
30
13
|
|
14
|
+
should_have_instance_methods :unpaid?, :ready?, :redeemed?, :suspended?
|
15
|
+
should_have_instance_methods :was_unpaid?, :was_ready?, :was_redeemed?, :was_suspended?
|
16
|
+
|
17
|
+
context 'Finders and scopes' do
|
18
|
+
should 'return adequate shit' do
|
19
|
+
for st in %w(unpaid ready redeemed suspended)
|
20
|
+
assert_same_elements Order.find_all_by_state(st), Order.send(st)
|
21
|
+
assert_same_elements Order.find_all_by_state(st), Order.send("find_all_#{st}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
31
26
|
should_validate_presence_of :state, :message => default_error_message(:inclusion)
|
32
27
|
|
33
28
|
context 'A fresh order' do
|
34
|
-
|
35
|
-
@order = Order.new
|
36
|
-
end
|
29
|
+
subject { Order.new }
|
37
30
|
|
38
31
|
should_allow_values_for :state, 'unpaid'
|
39
32
|
should_not_allow_values_for :state, 'ready', 'redeemed', 'suspended', 'screwed_up',
|
@@ -42,9 +35,7 @@ class OrderTest < ActiveSupport::TestCase
|
|
42
35
|
end
|
43
36
|
|
44
37
|
context 'An unpaid order' do
|
45
|
-
|
46
|
-
@order = orders(:unpaid)
|
47
|
-
end
|
38
|
+
subject { orders(:unpaid) }
|
48
39
|
|
49
40
|
should_allow_values_for :state, 'unpaid', 'ready', 'suspended'
|
50
41
|
should_not_allow_values_for :state, 'redeemed', 'screwed_up',
|
@@ -53,9 +44,7 @@ class OrderTest < ActiveSupport::TestCase
|
|
53
44
|
end
|
54
45
|
|
55
46
|
context 'A ready order' do
|
56
|
-
|
57
|
-
@order = orders(:ready)
|
58
|
-
end
|
47
|
+
subject { orders(:ready) }
|
59
48
|
|
60
49
|
should_allow_values_for :state, 'ready', 'redeemed', 'suspended'
|
61
50
|
should_not_allow_values_for :state, 'unpaid', 'screwed_up',
|
@@ -65,9 +54,7 @@ class OrderTest < ActiveSupport::TestCase
|
|
65
54
|
end
|
66
55
|
|
67
56
|
context 'A redeemed order' do
|
68
|
-
|
69
|
-
@order = orders(:redeemed)
|
70
|
-
end
|
57
|
+
subject { orders(:redeemed) }
|
71
58
|
|
72
59
|
should_allow_values_for :state, 'redeemed', 'suspended'
|
73
60
|
should_not_allow_values_for :state, 'unpaid', 'ready', 'screwed_up',
|
@@ -76,9 +63,7 @@ class OrderTest < ActiveSupport::TestCase
|
|
76
63
|
end
|
77
64
|
|
78
65
|
context 'A suspended order' do
|
79
|
-
|
80
|
-
@order = orders(:suspended)
|
81
|
-
end
|
66
|
+
subject { orders(:suspended) }
|
82
67
|
|
83
68
|
should_allow_values_for :state, 'suspended', 'redeemed', 'ready', 'unpaid'
|
84
69
|
should_not_allow_values_for :state, 'screwed_up', :message => default_error_message(:inclusion)
|
@@ -87,3 +72,4 @@ class OrderTest < ActiveSupport::TestCase
|
|
87
72
|
should_not_require_attributes :txref, :redeemed_at, :facility_id
|
88
73
|
end
|
89
74
|
end
|
75
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omg-statelogic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: "1.1"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Igor Gunko
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-11 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -64,7 +64,8 @@ files:
|
|
64
64
|
- rails/init.rb
|
65
65
|
has_rdoc: true
|
66
66
|
homepage: http://github.com/omg/statelogic
|
67
|
-
|
67
|
+
licenses:
|
68
|
+
post_install_message: v1.1 introduces changes that may (or may not) be incompatible for you. Please review them at http://github.com/omg/statelogic
|
68
69
|
rdoc_options:
|
69
70
|
- --line-numbers
|
70
71
|
- --main
|
@@ -86,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
87
|
requirements: []
|
87
88
|
|
88
89
|
rubyforge_project:
|
89
|
-
rubygems_version: 1.
|
90
|
+
rubygems_version: 1.3.5
|
90
91
|
signing_key:
|
91
92
|
specification_version: 2
|
92
93
|
summary: Another state machine for ActiveRecord
|