omg-statelogic 1.0.2 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|